diff --git a/.gitignore b/.gitignore index 2731ccb..26e94f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -!sqlite-jdbc-3.34.0.jar -Mobile_Atlas_Creator_UNLOCKED.jar build mapsources mobac-rev.properties diff --git a/CHANGELOG.txt b/CHANGELOG.txt new file mode 100644 index 0000000..4f817c3 --- /dev/null +++ b/CHANGELOG.txt @@ -0,0 +1,824 @@ +******************************************************************************* +* M O B I L E A T L A S C R E A T O R * +******************************************************************************* +* V E R S I O N I N F O R M A T I O N * +******************************************************************************* + + + = Additions since previous version + ! = Bug fixes since previous version + ~ = Changes since previous version + - = Features that has been removed + +======= +2.3.3 (2023-10-13) + ! BSH map sources: fixed Cannot access method addRequestProperty when using + Java 17+ (#383) + ~ Custom map sources: validate map source names for disallowed characters + - Map source "4uMaps" removed (service discontinued) + +2.3.2 (2023-09-29) + ! MBTiles: prevent duplicate tiles in mbtiles database + ! MBTiles: atlases are now restricted to one map per zoom level + ~ Updated Mapsforge to 0.20 + +2.3.1 (2023-01-18) + ! Mapsforge: VALIDATE_COORDINATES=false to avoid problems at the borders of + the world + ! "Show Readme" menu command fixed (#380) + ! MBTiles bounds changed to match the specification: "Bounds must define an + area covered by all zoom levels." + +2.3.0 (2022-08-11) + ~ Mapsforge library updated to version 0.18 + ! Fixed PNG 4bit/8bit tile processing + ! Fixed problems with the used Berkeley DB JE on systems with Turkish locale + (tile store database library was upgraded to version 5.0.73) + ~ MBTiles database format upgraded to 1.3 (minzoom/maxzoom added, FR #307) + + Added image format WEBP as tile type including detection on download + + Alpine Quest Map files (.aqm) can be used as local map source + + +2.2.3.2 (2022-05-15) + ! Fixed StackOverflowError when opening settings dialog (#372) + +2.2.3.1 (2022-05-09) + ! Fixed problems with MapEvaluator (missing resources #370) + +2.2.3 (2022-05-06) + ! Fixed fallback to English when a localized string is missing in the selected + language + ! Fixed min/max zoom info for SQLite based atlas: RMaps, BackCountry, OsmAnd + SQLite, Maverick, MBTiles, BigPlanet Tracks (#365) + ~ Detection of JPEG image type improved (more variants are now detected) + ~ Mapsforge library updated to version 0.17 + + customWmsMapSource: entry allows to switch between + meter/degree (replaces wgs84 parameter) + +2.2.2 (2022-01-31) + - Dropped support for Java 8 - Java 11+ is now required + ~ Allow transparent background on CustomMultiLayerMap (#359) + ! FreemapSlovakia maps updated + ~ Boolean fields in custom map sources that can be true or false now only + accept one of those values + + BSH Tools method "alert" added + ! BSH map sources did not correctly apply ignoreError=true setting in + multi-layer maps and other occasions + ! Custom multi-layer XML map source: fixed a minor problem with mapping + alpha values to layers in case not all layers return an image + + Custom WMS map source support for v1.3.0 with EPSG:4171 and wgs84 mode + thanks to Nicolas Paour + ! Tile calculation fixed for local map sources + ~ Logging backend changed from log4j to slf4j+logback + +2.2.1 (2021-06-02) + ! Loading an MOBAC XML profile can cause java.lang.NullPointerException + ! "OsmAnd tile storage" atlas format: fixed file name scheme of generated + map tiles to "YYYYYYpng.tile" (#356) + ! Freemap Slovakia maps fixed (FR#306) + - Non-working maps "OSMapa-Topo..." removed + - Non-working map "FAA Sectional Charts" removed + - Non-working map "MoldovaPointMd" removed + ! Fixed bounds calculation for negative lat/lon values for MBTiles and + GeoPackage maps (#358) + +2.2.0 (2021-04-10) + ! MOBAC build system changed to Gradle + + Support for ARM based MacOS systems (SQLite library) + - Support for 32bit systems dropped + ! fixed Jaxb problem causing a NullPointerException with defineClass + is null (#355) + +2.1.4 (2020-12-22) + + Russian translation added (thanks to xmember) + + Preview map view: Show detailed error in each tile if download had failed. + ! Default map tile expiration time was not correctly applied when the server + does not provide an expiration time (see #342). + ! TileDownloader ignored used customized settings (e.g. expiration times) + see #342 + ! Correct handling of tile counter for multi-layered local map sources (#345) + ! Custom map sources with invertYCoordinate=true save tiles in cache to the + wrong (inverted) tile coordinate (#349). Note that fixing this issue means + that all saved tile caches of custom map sources have to be cleared as the + tiles are saved to invalid coordinates. + ! MBTiles bounds issue with multiple maps in one atlas fixed (#348) + +2.1.3 (2020-04-13) + ! Custom map sources with UTF-8 characters now loaded correctly on platforms + with a different default encoding than UTF-8 (fix for #324) + ! NullPointerException when creating an Magellan RMP (fix for #325) + + New map sources (covering Spain): Instituto Geográfico Nacional (IGN) + WMTS Base/MTM/PNOA (ortho) + + Measurement ruler on preview map added (patch #45) + + Allow to set HTTP headers that are restricted by Java in custom map sources. + Such as "Origin", "Connection" and other. + - Map source removed: "Chartbundle US World Aeronautical Charts" (#332) + - Map source added: "Chartbundle US Helicopter Charts" (#332) + ! Fixed: preview selection around GPX around not visible on the map (#333) + - Removed the undocumented feature to trust TLS certificates via settings.xml + ( and entries) + + Added entries to BeanShell and custom XML map sources to explicitly trust an + TLS certificate (via it's public key). The public key is identified via it's + sha-256 hash that can be placed in the custom map xml/bsh file. + + BSH map source tools method added: "getDirectory(...)" + + BSH map source tools method added: "calculateTileLatLon(zoom, x, y)" + +2.1.2 (2019-08-07) + ~ Minimum supported Java version increased to Java 8 (1.8) + ! "mapFile must not be null" error when creating an atlas + ! Save settings to settings.xml in UTF-8 format (fix for #324) + ! Map creation error with JPEG (Garmin Custom and others) (fix for #326) + + Add trusted certificate for HTTPS connections via settings.xml + +2.1.1a (2019-04-13) + ! NoSuchMethodException when clicking the "Create Atlas" button (fix for #321) + +2.1.1 (2019-04-10) + ~ Changed the MOBAC website URL (e.g. used for online update): + http://mobac.sourceforge.net -> https://mobac.sourceforge.io + ! Map source initialization by atlas creation engine added (fix for #313) + ! Multi-threading issue with TileImageWriter fixed + ~ On Linux now always xdg-open is used for opening the atlas folder in file + manager (#317) + +2.1.0 (2018-06-18) + ! 4uMaps.eu fixed + ~ Mapsforge updated to version 0.9.1 + - Removed: map source OpenPisteMap (does not exist anymore) + + JAXB libraries included into MOBAC (for Java 9+) + +2.0.1 (2017-11-11) + ! Fixed: Custom maps source loading problem when using custom map sources in a + custom multi-layer map source (#294) + ~ Clean-up: USGS map sources (some removed, some updated) + + Extra start commands for Java 9: + "start_java9.sh", "Mobile Atlas Creator Java9.exe" + +2.0.0 (2017-04-14) + ~ Mapsforge library updated to version 0.8.0 + ~ SQLite-jdbc library updated to version 3.16.1 + +2.0.0 beta 3 (2017-01-02) + ~ Mapsforge library updated to version 0.7.0 + ! Fixed multi-threading problem for MapsForge maps (truncated labels) + ~ Updated xerial sqlite-jdbc library to version 3.8.11.2 + ! Fixed: Mapsforge cusom map did not had an effect + + New: Mapsforge custom map property + - MapQuest map source deleted (map not available anymore) + + Custom Mapsforge Map: Multiple map files ( elements) are now + possible (see example) + ! Fixed: MOBAC on Windows now works when started on UNC network path + +2.0.0 beta 2 (2016-04-24) + ! Fixed New Zealand Topographic Maps (see bug #282 & patch #43) + - Removed maps: OpenStreetMap Mapnik and OpenSeaMap (maps are no longer + available for MOBAC) + + Left panel is now resizeable by mouse + + Refreshing the preview map view via "F5" now clears the label cache of + Mapsforge maps + + BeanShell map source: "displayName" added (allows to use non-ascii characters + as map name shown in MOBAC + +2.0.0 beta 1 (2015-11-26) + ~ Mapsforge library updated to version 0.6.0 + ~ Map pack update certificate re-created due to expired certificate. + The map pack update url changed, old MOBAC versions can no longer receive + map pack online updates. + ! NzTopoMaps updated to new schema + +2.0.0 alpha 4 (2015-09-01) + + Canada Toporama map source reactivated + ~ Mapsforge library updated to version 0.5.2 + +2.0.0 alpha 3 (2015-04-16) + ~ Mapsforge vector maps library updated to 0.5.1 + ! Mapsforge custom caching implemented (required for correct label rendering) + +2.0.0 alpha 2 (2014-10-31) + ! Fixed problems using mapsforge vector maps as a layer of a multi-layer map + ! TrekBuddyTar: test added for too long layer & map names + + Maverick: Old atlas format (.jpg.tile) reactivated as additional atlas format. + + New atlas format (experimental): GeoPackage + +2.0.0 alpha 1 (2014-07-31) + ~ GUI design improved + + Custom map sources can be grouped by subdirectories + + Direct rendering of bitmap tiles based on mapsforge vector maps + (see README.HTM for details). + +1.9.16 (2014-02-06) + ! Background color does not work in case of a multi-layer map source with + only one layer (#252) + ~ The atlas format Maverick was changed from OSMTracker format to RMaps + SQLite format (request from Maverick author). + +1.9.15 (2013-11-20) + + Selection around GPX track: preview map selection while selecting distance + + Selection enclosed by GPX track (inner region) + ! Minimum and maximum zoom level of custom multi-layer map sources in + combination with local file-based map sources corrected + ! Maverick: Corrected that all files are expected to have ".jpg.tile" + ! Maplorer: Custom tile width and height reactivated + extension, even if it is a PNG file. + + Updated xerial SQLite library that comes with MOBAC to v1.3.15-M1. + +1.9.14 (2013-07-29) + ~ Custom SQlite map sources can now be specified using a relative path + ~ BackCountry Navigator format updated - now SQLite based atlases are created + + Japanese translation added (thanks to "u/ta-ka") [patch #33] + ! Not translated tooltip corrected [patch #34] + ! A problem with MapSourceInitializationException fixed (#245) + ! Memory leak fixed in "TwoNav (RMAP)" atlas format causing an + OutOfMemoryError when creating a large atlas + +1.9.13 (2013-05-29) + ! HTML injection via Atlas name bug #242 + ! Workaround for Java bug in JPEG writer (if source image has alpha + transparency) implemented + + French translation added (thanks to Jean-Claude Repetto) [patch #31] + +1.9.12 (2013-04-17) + ! Mapsource OpenStreetMap Maps4u.eu updated + ~ Reduced the number of decimal places of coordinates in GPX files created by + MOBAC to 5 places (#242) + + Custom multi-layer map sources: Each layer can now have an alpha + transparency value, specified as space separated list in + element + ! Bufix of conversion between different coordinate formats (degree, deg/min, + deg/min/sec) + ~ localImageFile support using (patch by miocool) + ~ More atlas format support retina (scale = 2) images, including Paper(PNG), + Paper(pdf). (patch by miocool) + ! More atlas format can display retina (scale = 2) images correctly + (convert to scale = 1), such as iPhone v5 (patch by miocool) + + Add map source support (patch by miocool) + ! Bug fix of 512x512 map tile images in Multiple layer (patch by miocool) + + Multiple language for Simplify-Chinese, Traditional Chinese and English + (patch by miocool) + + View 512x512 map tile images for retina display (patch by miocool) + +1.9.11 (2013-02-19) + ! Bugfix for servers that send case insensitive content-types + ! Bugfix OruxMapsSQlite final commit was missing (patch #30) + + New map sources: USGS National Map Base/Satellite/Satellite+/Vector/Topo + ! Bugfix Garmin Custom Map: Removed possibility to set output format to PNG + +1.9.10 (2012-12-04) + ! Bugfix Local tile [zip] files in quadkey format causes a + NullPointerException when creating an atlas (#229) + + Custom multi-layer map source can now contain maps + +1.9.9 (2012-10-09) + ! Bugfix in PNGW calibration (patch by allib) + ! RMAPS: Error "failed to retrieve max tile zoom info" fixed (#3561323) + ! GEMF: Error "NullPointerException" fixed (#3564146) + ~ OruxMaps: Patch #3300055 applied + + Custom XML map: now works in simple XML map, too + + Loading multiple GPX files at once into MOBAC (based on patch by heckie) + ! Bugfix NullPointerException when aborting atlas download fixed (#3568849) + + Automatically splitted maps because of the specified maximum map size can + now overlap 1-5 tiles + +1.9.8 (2012-07-05) + ! Viewranger atlas format depends on Java Advanced Imaging without checking + ! OurxMaps SQLite: Memory handling changed (should prevent OutOfMemoryError) + ! Fixed progress bar in atlas progress window for large atlases + + Possibility added to use SQLite Java Wrapper (ch-werner) instead of default + sqlite library + ~ Replaced the old SQLite library with recent version of Xerial. This fixes + all problems creating databases larger than 2GB on Windows 64bit + ! CacheWolf: Custom tile processing re-enabled + + New atlas format: iPhone 3 Map Tiles v5 + +1.9.7 (2012-05-16) + + Custom XML map source: New parameter {$q} for Quad-Tree encoded zoom, x & y + + New atlas output format: Osmdroid GEMF + + Increased default map size to 65536 + +1.9.6 (2012-04-02) + + New settings.xml option: + + New atlas format: TomTom raster + - Map source removed: Openstreetmap Osmarenderer (project has been retired) + ! Paper atlas: Disabling compass in settings was ineffective + + New map source: OpenStreetMap 4uMaps.eu (Europe) + + backgroundColor option for customMultiLayerMapSource + ! Message "The JPEG image format is not supported by OpenJDK." was shown at + start-up even is custom tiles processing was disabled + + New atlas format: Viewranger + ~ Magellan (RMP): Removed 18000 pixel check + +1.9.5 (2012-03-09) + ! Alpine Quest Map: Multiple bugs fixed (#3484328) + ~ Improvements in atlas download progress dialog (patch by dvodvo) + ~ Windows launcher "Mobile Atlas Creator.exe" increased max heap size to 1GB + ~ Linux start.sh increased max heap size to 1GB + + New selection mode: Circle (approximated by a 16 point polygon) + + New map source: OSMapa-Topo with contours (PL) + +1.9.4 (2012-01-29) + + BeanShell map source: ignoreError=true feature added + + Debug menu: Show/hide map tile borders + +1.9.3 (2011-12-01) + + Custom map source from local tiles XML schema changed: + new values: DIR_ZOOM_X_Y, DIR_ZOOM_Y_X, QUADKEY + removed flipXYDirs (use DIR_ZOOM_Y_X instead + ! Custom map source from ZIPs: Handling for atlas types with two file + extensions fixed + ! Bugfix Osmdroid SQlite: PRIMARY KEY must be unique (#3438206) + ~ Turaterkep map updated (renamed internally to Turaterkep256 because of map + format change) + + Support added for starting external tools from within MOBAC + +1.9.2 (2011-10-12) + + Custom map source from ZIP/files in file-system: added possibility to invert + y coordinate via "invertYCoordinate" like it is used by MapTiler + + New settings.xml option: (default 1). Allows to reduce + or increase the maximum attempts MOBAC tries to download a tile in case + of errors occur while download or HTTP response is not as expected. + + Logging verboseness now configurable for the current session via GUI + ! PaperAtlas: NullPointerException when WGS Grid=off has been fixed + + CustomSQLite atlas as map source: OSMAND format added + + New atlas output format: OSMAND SQLite + +1.9.1 (2011-09-09) + ! Opening settings dialog: ClassCastException on Linux/OpenJDK + ! Custom SQlite atlas as map source fixed for atlas formats AndNav, + BackCountry Navigator and Osmand + + Background color for BeanShell map sources can be specified by adding + backgroundColor = "#ffffff"; + ! Custom SQLite atlas as map source had an undefined tileImageType; + Added auto-detection and user defined + +1.9 (2011-08-18) + ! Calculation problem in MGMaps atlas format (fix by Pierre-Luc Paour) + ! Custom mapsource from RMaps SQLite atlas shows wrong zoom levels + - Removed map source: Open Cycle Map (request by Andy Allan) + + New map source: OSMapa-Topo (Poland) + + Map source tile store coverage: button for hiding colored layer added + + OziExplorer/Trekbuddy: MM1B calculation improved (patch by MrPete #3026830) + + Custom XML map source: {$serverpart} / implemented for + balancing load among multiple servers with different DNS names + + SQLite library included in MOBAC distribution + +1.9 beta 6 (2011-06-21) + + New atlas format: Geocaching Live offline maps + + New atlas format: MBTiles (Experimental) + + New atlas format: Paper Atlas (PDF) & Paper Atlas (PNG) + [provided by Ľubomír Vasek] + ! Bug #3316081 - "String index out of range: -1" upon map sources update + ! Incorrect selection and tile count calculation + + New map source: Moldova (point.md) + +1.9 beta 5 (2011-05-17) + + Added possibility change directory syntax for file and zip based map sources + from zoom/x/y to zoom/y/x ("flipXYDir") + + Added possibility to use and within a custom + multi-layer map source + ! CustomMultiLayerMapSource: "null" error when loading + ! directories.ini: mobac.atlasprofilesdir not used for loading profiles list + + directories.ini: System variables can be used in the form ${VARNAME} + + Local map sources from SQLite atlases can now be used - supported formats are + RMaps, MBTiles, BigPlanetTracks, Galileo, NaviComputer + ! Fixed OpenStreetMap Cycle Map + + Experimental: adding user-defined polygon maps + ~ Changed polygon selection behavior - selection stays now after adding it + +1.9 beta 4 (2011-05-02) + ~ Problem loading tile image type for custom map sources (ends up for TrekBuddy + atlas format in an NullPointerException like in bug #3290976 + ~ Settings dialog now lists all tile stores - not only the stores of loaded map + sources + + Experimental: Polygonal map derived from GPX track segment + ! Endless opening of exception dialog (endless recursion) + +1.9 beta 3 (2011-04-21) + + Map source UMP-pcPL reactivated + + [Nokia] Sports Tracker file extension changed to jpg (feature request #3066161) + + Reactivated atlas format "TwoNav (RMAP)" + + New map source: FAA Sectional Charts (aeromaps.us) + + Reactivated map sources Freemap.sk (Car atlas, Hiking map, Cycle map) + + Map source New Zealand Topographic Maps (nztopomaps.com) reactivated + ! OruxMapsSQLite: Last processed tiles missing in db file + +1.9 beta 2 (2011-04-06) + ! Custom atlas map source / locally generated tiles map source + + New map source for using tiles from zip file(s) + + Removed all map sources except the OSM related - for details see + http://sourceforge.net/projects/mobac/forums/forum/861096/topic/4470412 + +1.9 beta 1 (2011-03-29) + + New map source: OpenStreetMap MapQuest + + New map source: OpenStreetMap Bing layer (Mapnik powered by Microsoft) + ~ Maximum zoom level of OpenStreetMap Mapnik decreased to 16 (zoom levels + 17+ are blocked on server side because of high server stress for + generating such tiles) + + New custom map source type: reading tiles offline from an OSMTracker/AndNav/ + BackCountry Navigator/Maverick/OSMAND atlas (from file system) + ~ Atlas format PNG+Worldfile: projection file for Arcgis added and calculation + improved (patch by user mmartin2) + ~ JPEG compression level selectable for Magellan (RMP) atlas format + +1.9 preview 14 (2011-03-17) + + Osmdroid SQLite: Tile image format conversion implemented + - Osm Hiking maps removed (excluding the "Wanderreitkarte Abo" version) + - Outdooractive.com maps removed as requested by map provider + +1.9 preview 13 (2011-03-12) + + Download to tile store without creating an atlas: + new atlas format "Tile store download only" + ! BeanShell map sources could not be used with certain atlas formats + + New map source: Israel Topo (Amudanan) with and without trails + +1.9 preview 12 (2011-03-05) + ~ Cykloatlas: max zoom level extended to 16 + + New map source: Canada Toporama + + Convert an existing atlas profile to a different output format + ! Loading of custom CloudMade maps fixed + +1.9 preview 11 (2011-03-02) + ! Error when using a BeanShell map source with certain atlas formats + - Removed Map+ map sources because of license problem with swisstopo + +1.9 preview 10 (2011-02-28) + ! Fixed map source: Docelu.pl + + Bookmarks can be added (saves map position and selected map source) + ! Fixed map source: Cykloatlas and relief + ! Fixed map source: Map+ (Switzerland) + + New map source: Map+ Gelände (Switzerland) + + New atlas format: nfComPass + +1.9 preview 9 (2011-02-22) + + New map source: Reit- und Wanderkarte (Abo) - (requires purchased ticket) + ~ Updated New Zealand Topographic Maps url + ! OpenStreetMap attribution + MOBAC user aget + +1.9 preview 8 (2011-02-16) + + NaviComputer: Possible to change tile image format (PNG, 4Bit-PNG, JPEG, ...) + + OpenPisteMap: All three layers (base, contours and landshed are now supported) + - Disabled TwoNav RMAP output format because of legal/license problems + +1.9 preview 7 (2011-02-04) + + OSM Hiking ticket system implemented (Wanderreitkarte.de) + ! NoSuchMethodError: mobac.program.ProgramInfo.getUserAgent()Ljava/lang/String; + +1.9 preview 6 (2011-02-04) + ! Custom tile size was not available for TrekBuddy and Glopus GFM + ~ Tile usage policy implemented for OSM Mapnik + +1.9 preview 5 (2011-01-21) + + New map source: ICAO Maps (Germany) + + Manual map pack online update via settings dialog + + Add selection via Ctrl+A key combination possible (see "Maps" menu) + +1.9 preview 4 (2011-01-14) + + New: Support for CustomWmsMapSource (experimental) + + Download bandwidth limitation selectable for very fast network connections + ! Highest zoom level missing in tile store coverage zoom selector + + New atlas format: OsmdroidSQlite + + New map sources: ArcGIS topo map/satellite/street map + +1.9 preview 3 (2011-01-09) + + New atlas format: PNG + Worldfile (PNG & PGW) + ~ Atlas output format has to be chosen before adding maps + ~ Disabling of unsupported tile processing options (regarding the current + atlas format) + ~ Enabled maps with ellipsoid projection for RMaps + +1.9 preview 2 (2010-12-18) + + New atlas format: BackCountry Navigator + + New atlas format: TwoNav (RMAP) + + Multi-layer maps with more than two layers are now possible + + New map source: OSM Hiking with relief and base + + New map source: Open Sea Map (sea layer joined with Mapnik) + + New atlas format: MGMaps/MyTrails (MGM) + + New map source: Topomapper.com + ~ Map sources are now packed into "MapPacks" which can be updated + without changing the main MOBAC program + ~ Custom map sources are moved from settings.xml into separate xml files + in the "mapsources" sub-directory + ~ XML structure of multi-layer custom maps sources has changed + + Multi-layer maps can now contain map sources that come with MOBAC + This allows to combine existing map sources with new overlays. + + BeanShell map sources can be used if placed in the "mapsources" + sub-directory + + All direcories used by MOBAC can be pre-configured via file + directories.ini in the MOBAC program directory + + CustomMap: new parameter: ignoreErrors and backGroundColor can have + alpha transparency parameter + + New map source: Cloudmade Map default style (1) + + Tile image format conversion for RMaps/BigPlanet/Galileo + + 1.8 final: (2010-10-31) + + New map source: New Zealand Topographic Maps + + 1.8 RC 1: (2010-10-23) + + AlpineQuest handles tiles <> 256px and ellipsoid projections + + New atlas format: Run.GPS Atlas + ! Fixed map source: Emapi.pl + + 1.8 beta 4: (2010-10-09) + ~ Implemented logging for ImageWriter warnings + ~ Display selected areas: adding a new map selection does no longer resets the + map selection and therefore the highlighted area does not change. + + 1.8 beta 3: (2010-10-02) + ! Fixed: NullPointerException when renaming an GPX file entry + ! MyTopo URL updated and fixed + ~ Unnecessary restriction of RMaps / BigPlanet Tracks to zoom 17 removed + + New map source: Microsoft Maps with hill shade + ~ Custom tile settings now possible with SportsTracker + + New atlas format: Osmdroid ZIP + + New map source: SIGPAC Mercator (Spain only) - patch by susinho + + 1.8 beta 2: (2010-09-13) + + AlpineQuestMap atlas creator updated (patch by Camille) + + New map source: Navitel (Russian) + ! GPS Sport Tracker: space removed in tile file name + ! MyTopo URL updated + + 1.8 beta 1: (2010-08-24) + ! Fixed PNG 256 color output + + New atlas format: OruxMaps (Android) + + New atlas format: Glopus Map File (AFTrack and others) + ~ BigPlanet SQL commit rate changed + ! #2963490 Using custom tile size with multi-layer maps creates black map + tiles + + GPX file editor improved + ~ Austrian Map removed (does not work anymore - unable to fix) + + Yandex Map & Sat added (works only with selected atlas creators because of a + different projection category - Yandex uses an ellipsoid) + ~ Map source change: Emapi.pl replaces Emapa.pl + + New atlas format: PathAway + ! Alpha transparency problem with multi-layer maps + + New atlas format: AFTrack (OSZ) + ~ CacheBox layer name uses now the map source name + + New atlas format: AlpineQuestMap (AQM) + + New atlas format: Ublox + ! Fixed OSM Hiking relief + + New map source: Cykloatlas with relief + + Custom Map Sources extended to multi-layer map source (2 layers) + + New map source: Statkart sea/nautical (AKA "sjo_hovedkart2") + ~ TouretechQV: Corrected "projparams" (removed unset UTM zone) - see #2970353 + + New atlas format: Google Earth Overlay (unrestricted Google Custom Map) + ! Fixed: #3008934 (MM1B calculation problem in .map file) + + New map source: MyTopo.com (USA only) + + New map source: Yahoo Maps Japan + + New atlas format: GPS Sports Tracker + + New atlas format: Sports Tracker + + New map source: OSM Hikebikemap.de + + Background color for custom maps added + ~ Freemap.sk maps updated and changed + + New atlas format: Maplorer + + New map source: Yahoo Taiwan + + New map sources: Aero Charts VFR/IFR/IFR-H (USA only from runwayfinder.com) + + New atlas format: OruxMaps Sqlite + + New map source: Ordnance Survey Explorer Maps (UK) + + Proxy authentication by user name/password added in GUI + + New atlas format: OSMAND + ~ SQLite back-end replaced - Zentus SqliteJDBC is now used + (see README.HTM for details) + ! OpenPisteMap tile url updated + + New atlas format: NaviComputer + + 1.7: (2010-02-05) + ~ Project has been renamed to "Mobile Atlas Creator" taking account that + besides TrekBuddy a large number of atlas and map formats are supported + and for ending the mix-up of "TrekBuddy" and "TrekBuddy Atlas Creator" + ~ Tiles tore now uses database (BerkelyDB) instead of tile files in file + system + + Old tiles saved in the tile store are checked and updated when used + (displayed in map view or used in an atlas). Updating is done via + expiration settings - those provided by the server or otherwise user + specified. + + Atlas output directory can be specified via settings dialog + + AndNav and OSMTracker: Tile format conversion (JPG <->PNG) implemented + including color reduction + ~ Docelu.pl can update it's base URL like the Google map sources do + ~ Pause/resume button now works while map creation (not only while download) + + New experimental map source: Turaterkep (Hungary hiking) + Uses tiles of size 512x512 (not supported by all atlas formats) + + Multi-layer map sources such as Google Hybrid or OSM Hiking with relief + background can be used with all atlas creators + + New map: NearMap Australia (high-resolution aerial images for Australia) + ! GPX addWpt: Multiple way points added by one mouse click fixed + ! Start.sh/Start.cmd Java max heap setting was ignored by Java because of + the position at the end of the command line + ! #2904937 and #2905182 1px map calibration bug + + New map source: Humbermedia Bavaria + + New atlas format: Mobile Trail Explorer Cache (writes single MTECache file + per atlas) + + New map sources: (Norway) Statkart Topo2, Toporaster2 (limited to 10.000 + tiles per day and IP) + + Drag & Drop for maps in "Atlas content" tree + + New atlas format: Magellan RMP / VantagePoint + + New atlas format: Touratech QV + ! Fixed #2913874: ArrayIndexOutOfBoundsException in PNG 4-bit writer + + New map source: Eniro.com map/aerial/nautical (Sweden, Norway, Finland) + + Checkbox added in atlas progress dialog for ignoring all download errors + + New atlas format: CacheWolf (as one large 24bit png + WFL or tiled with + multiple WLF files using the configured image format and tile size) + + New map source: Mapplus.ch (Switzerland) + + Coordinate format changeable ("deg" / "deg,min" / "deg,min,sec") + + New atlas format: CacheBox + + New atlas format: Garmin Custom Map + Image downscaling uses bilinear filter (improves image quality) + + Each map source has now a background color (usually black) that is used + in case of missing tiles + + Content-type check after download (HTTP header and image data header) + + New map source: Ovi/Nokia Maps + + New map source: Bergfex (Austria) + ! Grid paint juddering on high zoom levels fixed + ~ OpenStreetMap Hiking updated + + 1.6.1: (2009-10-30) + ! Loading and saving of GPX failed + + 1.6: (2009-10-27) + + Loading & saving of GPX 1.1 files (way- track- and routepoints are displayed + as overlay) + + GPX 1.0 files are automatically transformed to GPX 1.1 file on load + + Route and tracks are painted as connected line + + Add new way points to a GPX file (properties: lat, lon, name) + + Map scale bar added (metric/imperial selectable) + + New atlas format: Mobile Trail Explorer (MTE) + + New atlas format: RMaps / BigPlanet SQLite (Android applications, requires + additional SQLite libraries) + + New atlas format: OSMTracker + + New map source: OpenStreetMap Public Transport (öpnvkarte.de) + + New map source: AustrianMap (z14 & z15 of www.austrianmap.at) + [provided by Guenther Hoelzl] + + New map sources: Freemap Slovakia (normal, hiking & hiking plus hill shade) + + New map sources: Google Maps Korea + + New map sources: Open Piste Map (openpistemap.org) + + New atlas format: Maverick (Android application) + + New map sources: Emapa.pl (Poland) + + New atlas format: Glopus (PNG & KAL) + + New map sources: Outdooractive.com Austria and South Tyrol + + ~ Max zoom level of Google Maps increased from 17 to 19 + ~ Behavior on adding new maps and layers changed: the number of layers has + been reduced to a minimum making it easier switch between different zoom + levels when using TrekBuddy + + ! Extreme performance break-in in grid-mode fixed + ! Map selections do no longer unwanted enlarge itself in grid mode beyond the + selected grid + + 1.5: (2009-08-01) + + Flexible atlases containing different areas of multiple map sources are possible + + New atlas output format: AndNav - Android Navigation System http://www.andnav.org + + Atlas download can be paused/resumed interactively + + Proxy settings rewritten - now system/Java wide or application settings can be + used alternatively to the user defined proxy + + New regional map sources (Poland): ump.waw.pl and docelu.pl + + Map sources can now be disabled which hides them from the list + + Merging different layers via drag & drop + + Custom map sources can be defined via settings.xml (see README.HTM) + + Map sources manual online update via settings dialog + + New atlas format: OziExplorer / large PNG export + + ~ Java requirement has changed: Now at least Java 1.6 is required! + ~ Profile saving updated to new atlas structure + ~ Fullscreen mode is currently unavailable + ~ Google Maps, Earth, Mapmaker, Maps China url updated + ~ Settings.xml format has changed + ~ Max zoom for Cycloatlas changed from 14 to 15 + ~ Removed OpenArialMap map source + ~ Panels on the left can be collapsed to save space + + ! Editing the atlas content while map creation in progress resulted in + unusable/abnormal atlases (see bug #2819613) + + 1.1: (2009-05-13) + + New output format: JPEG with different quality levels + + added map source Microsoft Maps China (Ditu) + + ~ Fixed url and name of Cykloatlas (fixes also bug #2755108) + ~ Updated url of Google Map Maker & Earth + ~ Fixed tar creation which had problems with default charset on some systems + ~ Changed the color depth selector to an output format selector + ~ OSM Hiking map moved to new server - url adapted + + ! "Open atlas folder" does now work on Linux (Gnome and may be Kde) + + 1.0: (2009-04-10) + + + Reload current map view by pressing "F5" + + First experimental implementation of color reducing implemented (requires + additional library "Java Advanced Imaging": https://jai.dev.java.net/binary-builds.html + Download the library and place the Jar[s] in the same directory as TrekBuddyAtlasCreator + + Experimental: Color reduced (<16) png files are saved using an own implementation + that writes real 4 bit PNG files (instead to the default Java one that only creates + 8 bit or true color files) + + added map source OSM hiking: http://opentiles.com/nop/ + + added map source OpenArialMap + + ~ Maximum map size reduced to 32767 (1 pixel less) + ~ Atlas output format can now be specified: Tared or untared atlas. The created atlas + is always created in the folder "atlases" - the folder "atlasestared" is no longer used. + ~ "ozi" / "tac_tmp" directory no longer used. Instead one temporary tar file per map + layer is created (and later deleted) in the default system temp directory + ~ fixed GoogleMapMaker map source + + ! Loading tile store information in settings dialog blocked GUI + + 0.9.7: (2009-03-05) + + + New map sources (full support): Microsoft Maps, Earth, Hybrid, + Cycloatlas (Czech Republic only) + + New map sources (partial support): Multimap.com + + Window position, size and state (maximized or not) is saved + + Preview map allows zoom move/zoom via keyboard controls (patch by Martin Loetzsch) + + Fullscreen mode hides left panel and places control inside the preview map + (patch by Martin Loetzsch) + + ~ Google Maps, Earth & MapsChina urls updated + ~ Custom tile size selection controls combined + ~ Fixed several Swing thread safety problems (patch by Martin Loetzsch) + + 0.9.6: (2009-01-08) + + + New map source: Google Terrain + + Download error counter added to atlas progress dialog + ! Updated OpenCycleMap url (fixes zoom level > 13) + + New map source: Yahoo Maps + + New map source: Google Maps China (Ditu) + + New map source (Germany only): Outdooractive.com + + Selected/entered tile size is now saved/restored in/from settings.xml + + Tooltip of "tiles-to-download-counter-label" (located right to the label + "Zoom levels (..)") now shows the breakdown of the number of tiles + to the different zoom levels including the area calculation + ~ Exceptions that occur while downloading/creating an atlas are now displayed + in an dialog showing detailed information about the system and the exception + ~ Updated Google Maps url & removed "Galileo" appendix + ~ New experimental implementation for creating tile of custom size. + Disdvantage: Much slower that the algorithm before + Advantage: Only constant memory needed (approx. less than 10 MB) + ~ Using custom tile size now does not concert the tiles to png format. + Instead the format used by the maps source is used. + + 0.9.5: (2008-10-27) + + + Detailed log files can be created by providing a configuration file log4j.xml + (see README.txt for details). + + HTTP Proxy (host & port) can be specified via GUI + + Added information about amount of tiles and total size for each tile source store + in Settings window. + + Multithreaded download of tiles implemented (number of parallel download threads + changeable via settings dialog + ~ Tile download system now reuses HTTP connections for HTTP 1.1 servers instead of + opening a new TCP connection for each tile + ! Selection of whole world resulted in a wrong max longitude (-180 instead of 180) + ! Tile number and index calculations near to the border of the world corrected + ! Saving profiles works now (including map source, zoom levels and tile size) + ! Aborting of stalled downloads works now as expected + + 0.9.1: (2008-10-17) + + ! Fixed wrong calculation of number of tiles when the amount was large. + + 0.9 alpha: (2008-10-15) + + Added resizeable GUI + + Added possibility to select map area by selection an area with mouse + + Added tmi files for the tared atlases which make the map loading faster + + ~ Changed preview viewer to JMapViewer. It has several advantages: + different map sources + preview loads in background automatically + easy zooming (mouse wheel) and movement (right mouse button) + ~ Tar generation rewritten, each tar is now only opened one time, not + once for each tile to be added (increases tar creation in case of a virus + scanner being active) + + 0.8: + + Added xml based settings file via Java Properties + + Added possibility to change tile size for the downloaded tiles. + + Added possibility to set map size in atlas. Giving the possibility to create + large atlases + + ! Fixed the non working setting tile store enabled. It was always enabled, + despite of what was written in the settings file + ! Fixed (hopefully) the generation of mixed up atlases at some Linux operating + system(s). + ! Fixed bugs related to defect profiles in profiles.xml file by adding some + validation of the xml data at application start. + +0.7: + + Added possibility to abort an ongoing download of Atlas + + Added label that shows how many tiles that will be downloaded with current + lat, long & zoom settings + + Added persistent tile store (cache of tiles in a store which is persistent + between program sessions) + + ! Fixed wrong download link to ditu.google.com + + 0.61: + + Added a possibility to select to download tiles from either ditu.google.com + or maps.google.com + + ! Fixed hard coded look and feel, which resulted in an + javax.swing.UnsupportedLookAndFeelException at other environments then Windows + + + + \ No newline at end of file diff --git a/CHANGES.md b/CHANGES.md deleted file mode 100644 index de8f87a..0000000 --- a/CHANGES.md +++ /dev/null @@ -1,4 +0,0 @@ -increased tile limit to 1 million -added the default open street map server -included sqlite driver by default -removed some broken mapsources that i didnt feel like fixing diff --git a/MOBAC.cmd b/MOBAC.cmd new file mode 100644 index 0000000..99574bf --- /dev/null +++ b/MOBAC.cmd @@ -0,0 +1,6 @@ +@Echo off +REM This file will start the TrekBuddy Atlas Creator with custom memory settings for +REM the JVM. With the below settings the heap size (Available memory for the application) +REM will range up to 1200 megabyte. + +start javaw.exe -Xms64M -Xmx1200M -jar Mobile_Atlas_Creator.jar \ No newline at end of file diff --git a/Mobile Atlas Creator.exe b/Mobile Atlas Creator.exe deleted file mode 100644 index 0c81047..0000000 Binary files a/Mobile Atlas Creator.exe and /dev/null differ diff --git a/README-DEV.html b/README-DEV.html new file mode 100644 index 0000000..1a8e729 --- /dev/null +++ b/README-DEV.html @@ -0,0 +1,207 @@ + + + + + Mobile Atlas Creator - Readme for Developers + + + +

Mobile Atlas Creator - Readme for Developers

+

Welcome to the developer documentation of Mobile Atlas Creator + (MOBAC). First please read the standard readme + for all users.

+ +

Table of contents

+ + +

Code access

+

If you want do get your hands on the latest source code of Mobile + Atlas Creator you can check out the code from the Subversion repository + at SourceForge:

+

https://svn.code.sf.net/p/mobac/code/trunk/MOBAC/ +

+

There you will find the latest sources of Mobile Atlas Creator in form of an Gradle project which can be imported for + example into IntelliJ. + All sources, tools and build files are included in this repository. + Java libraries are automatically retrieved from Maven central repository. +

+ +

Building Mobile Atlas Creator

+

+ If you want to compile MOBAC, an installation of Java Development Tools (JDK) is required. + Using OpenJDK version 8 or 11 is recommended. + For building MOBAC use the provided gradlew command-line script: +

+
+    # Linux/MacOS:
+    chmod u+x gradlew
+    ./gradlew dist
+
+    # Windows
+    gradlew dist
+
+ + +

MOBAC in IntelliJ

+

The main class for starting MOBAC in IntelliJ is in module mobac-run class mobac.StartMOBACdev

+ +

Guidelines for + publishing custom builds/releases

+

If you modify Mobile Atlas Creator and you want to publish it + yourself please consider the following guidelines:

+
    +
  1. Chose a version/release name that makes it clear that it is + not an official release: Change the version string to reflect that.
    + Example: 2.2 beta 3 XYZ edition
    + The version string is located in the file /build.gradle. + Change the entry version ... to your custom release name. +
  2. +
  3. Do not forget that Mobile Atlas Creator is a GPL project - + therefore publishing the source code together with the binary release + should went without saying. +
  4. +
  5. If your modification is useful you may consider to present it + to the Mobile Atlas Creator development team. Patches + are always welcome. Useful modifications have a great chance to be + integrated into the main branch. +
  6. +
+

Map sources and map packs

+

Since version v1.9 map sources are no longer part of Mobile_Atlas_Creator.jar. + All map sources implementation are located in jar files in the mapsources + sub-directory. Those map sources implementation packages are called + "map-packs". Map packs files always starts with the term mp- + and they end with the term .jar.

+

For implementing new map sources in a development environment + like Eclipse it is sometimes faster to load the map sources directly + from class-path rather from the map-packs. You can enable it by setting + devmode in settings.xml to true. Afterwards + map sources will be loaded directly from the bin directory of + Eclipse (if available).

+

Developing a custom map pack

+

For creating your own custom map pack you have to create a new module (Java) + inside /mappacks. for example /mappacks/mymappack

+

Place the map source code in directory /mappacks/mymappack/src/main/java/mobac/mapsources/mappacks/mymappack +

+

Additionally you have to create a text file named mobac.program.interfaces.MapSource + inside the directory src/main/resources/META-INF/services/. This + file contains a list of class names (full class name including the + package name, one per line) that should be loaded by MOBAC as map + source.

+

Background: During the build process this file will be included + into the map-pack jar as META-INF/services/mobac.program.interfaces.MapSource + so that it can be found by the ServiceLoader. +

+

Building the map pack

+

Map packs can be built separately using Apache Ant and the build target build_mapsources:

+
ant build_mapsources
+

Apache Ant is already included in Eclipse, so that you only have + to select the file build.xml, press the right mouse button and + select Run As - Ant Build.... In the dialogs that opens + deselect the build target all and select instead build_mapsources.

+

Each sub-package of mobac.mapsources.mappacks will be + compiled and packed to an map package. The created map packages are + saved into the mapsources directory. Therefore our example map + pack will be packed into the file mapsources/mp-mymappack.jar

+ + +

Source code overview - important packages

+

mobac.gui

+

This package contains the implementation of all dialogs/windows. + In the sub-packages you can find the related implementations of used + graphical components - e.g. mobac.gui.mapview.PreviewMap + - the component that draws the movable map background used by Mobile + Atlas Creator.

+

mobac.mapsources

+

Holds the infrastructure and the implementation of all map + sources available within Mobile Atlas Creator. For implementing own map + sources that uses an online map you should derive your map source from + the abstract base class mobac.mapsources.AbstractHttpMapSource. + Map sources should be compiled and packed to a map pack so that they can + be automatically detected and loaded while MOBAC is starting-up. For + details on that topic please read section Developing + a custom map pack.

+

mobac.program.atlascreators

+

Holds the implementations of all atlas creators (atlas output + formats) provided by Mobile Atlas Creator. Each class in the package + implements exactly one atlas output format. Of special interest is the + abstract class AtlasCreator + which is the super class every atlas creator is derived of. The list of + available formats is maintained in the enumeration mobac.program.model.AtlasOutputFormat. +

+ +

mobac.tools

+

This package contains additional stand-alone tools that are not + shipped with the Mobile Atlas Creator binary release. For example the mobac.tools.MapSourcesTester + downloads one tile from each map source for verifying that the map + source is functional.

+ +

Participation

+

If you are familiar with the programming language Java and you + want to contribute or participate in the development process of Mobile + Atlas Creator feel free to contact one of the other developers of + Mobile Atlas Creator.

+ + \ No newline at end of file diff --git a/README.html b/README.html new file mode 100644 index 0000000..e8f074e --- /dev/null +++ b/README.html @@ -0,0 +1,1521 @@ + + + + + Mobile Atlas Creator - Readme + + + +

Mobile Atlas Creator - Read-me

+

Welcome to Mobile Atlas Creator read-me file for end users.

+

Before January 2010 this project was known as "TrekBuddy Atlas + Creator".

+

+ Mobile Atlas Creator is an open source project hosted on + SourceForge.net:
https://mobac.sourceforge.io/ +

+

Table of contents

+ +
+ +

+ License +

+

+ Mobile Atlas Creator is under GNU General Public License Version 2 + (GPL). For details on the GPL see the license file gpl.txt.
+ The source code is available on the SourceForge.net + for download and in the project's + source code Subversion repository. +

+ +

+ Description +

+

+ Mobile Atlas Creator creates atlases for several applications. For + example TrekBuddy and Mobile + Trail Explorer (MTE), the Android applications AndNav, Maverick, Big Planet + Tracks, RMaps, + OruxMaps, the Pocket PC + application Glopus and the + commercial Windows application OziExplorer. + The map image created for OziExplorer can also be used with any PNG + capable image viewer (map image in one large PNG file). +

+ +

+ Requirements +

+

This application requires that a Java SE Runtime Environment 11 or higher is installed on the computer.

+

If you have the choice between different Java Runtimes you + should prefer the Java Runtime provided by Sun/Oracle. Especially the + OpenJDK has some bugs regarding MOBAC and tends to crash on certain + situations.

+ +

+ Installation +

+

+ Copy or move the unzipped files to a folder where you would like to + have Mobile Atlas Creator installed. On computers running Windows + please make sure not to install MOBAC into + Program Files sub-directory! + +

+ +

+ Application start +

+

Windows

+

+ The application is started by executing the Mobile Atlas Creator.exe. + During the first application start all necessary files and folders are automatically created by the application. +

+

Linux and OSX

+

+ You can start MOBAC by executing the start-up script start.sh. + Before starting MOBAC the first time it may be necessary to set the executable bit + for start.sh e.g. by executing the following command: +

+
chmod u+x start.sh
+

During the first application start all necessary files and folders are automatically created by the application.

+
+ +

+ The different atlas formats +

+ +

+ AFTrack OSZ +

+

+ For creating atlases compatible with AFTrack (Symbian S60) you have to + select AFTrack (OSZ) as format in atlas format selection dialog + that appears when starting a new atlas (menu Atlas entry New + Atlas). +

+

+ OSZ is a ZIP-archive. Within this zip archive a (large) number of + tiles with the calibrated folder structure (coordinates) are stored. + OSZ only works if each tile has got a resolution of 256x256 Pixels. So + be sure to uncheck Recreate/adjust map tiles (CPU intensive). +

+

The output format is one file for each layer in the + corresponding folder.

+

+ Restrictions +

+

Depending on the device free memory the file maybe not work. So + more then 80000 tiles should not be used.

+ +

+ AlpineQuestMap (AQM) +

+

Sorry no further details are available for this atlas format.

+ +

+ Creating and using atlases with AndNav +

+

+ For creating atlases compatible with AndNav you have to select AndNav + atlas format as format in atlas format selection dialog that appears + when starting a new atlas (menu Atlas entry New Atlas).
+ As atlases for AndNav do not support all features provided by Mobile + Atlas Creator the following settings are ignored when creating atlases + for AndNav: +

+
    +
  • Change height or width of the map tiles
  • +
  • Name of all layers and maps
  • +
  • Structure of the atlas (which maps belongs to which layer)
  • +
+ +

+ Creating and using atlases with Big Planet + Tracks +

+

+ For creating offline atlases compatible with Big Planet + Tracks (Android application) you have to select Big Planet + Tracks SQLite as format in atlas format selection dialog that appears + when starting a new atlas (menu Atlas entry New Atlas).
+ The atlas format BigPlanet SQLite does not support all features + provided by Mobile Atlas Creator the following settings can not be + used or are ignored when creating atlases using this output format: +

+
    +
  • Recreate/adjust map tiles with custom tile size (height and +
  • Name of all layers and maps
  • +
  • Structure of the atlas (which maps belongs to which layer)
  • +
  • Atlases created after another are merged into one Database + named [Atlasname] atlas.sqlitedb which is located in the + atlas output directory. +
  • +
+ +

+ Creating atlases for CacheWolf +

+

+ For creating atlases compatible with CacheWolf + you have to select CacheWolf WFL as format in atlas format + selection dialog that appears when starting a new atlas (menu Atlas + entry New Atlas). +

+

Custom tile processing settings enabled

+

Maps that have custom tile processing options set are saved as + tiled images with one WFL calibration file for each tile. All + processing options such as image format and tile size can be used.

+

Custom tile processing settings disabled

+

+ In this mode automatic tiling is disabled and the same restrictions and the warning + as for the OziExplorer output format apply. +

+

+ The output format of an "atlas" for CacheWolf is one subdirectory per + layer and within this subdirectory one + PNG + image and one + WFL + file per defined map. +

+ +

+ Creating Garmin Custom maps +

+

+ For creating atlases of Creating Garmin Custom maps you have to select + Garmin Custom Map (KMZ) as format in atlas format selection + dialog that appears when starting a new atlas (menu Atlas entry + New Atlas).
Details about the Garmin Custom Map format + can be found in the Garmin + Forums +

+

Using this atlas output format the following features are + ignored when creating atlases:

+
    +
  • Recreate/adjust map tiles (custom tile size and image format)
  • +
+

+ The output format of an "atlas" for Garmin Custom maps is one + KMZ + file per layer containing all maps (max 100) as separate + JPG + image files. The JPEG compression rate can be specified for each + map/image using image format selector in the custom tile processing + section. The Garmin Custom Map format defines a maximum image size of + 1024x1024 pixels. If a map is larger it will be automatically scaled + down to fit into this size. You can prevent scaling when setting the + max map size in the settings dialog to 1024. +

+ +

+ Creating atlases for Glopus +

+

+ For creating atlases compatible with Glopus you have to select Glopus + (PNG & KAL) or Glopus Map File (GMF) as format in atlas + format selection dialog that appears when starting a new atlas (menu Atlas + entry New Atlas). +

+

Glopus (PNG & KAL)

+

+ Using this atlas output format the same restrictions + and the warning as for the OziExplorer + output format apply. +

+

+ The output format of an "atlas" for Glopus is one subdirectory per + layer and within this subdirectory one + PNG + image and one + KAL + file per defined map. +

+

Glopus Map File (GMF)

+

+ Within this file a (large) number of tiles with its calibrated + coordinates are stored. Glopus works best if each tile has a + resolution of 1024x1024 pixels. So check Recreate/adjust map + tiles (CPU intensive). Width and height should be set to 1024. +

+

The output format is one file for each layer in the + corresponding folder.

+ +

+ Glopus Map File (GMF) / AFTrack +

+

+ For creating atlases compatible with AFTrack (Symbian S60) you have to + select Glopus Map File (GMF) as format in atlas format + selection dialog that appears when starting a new atlas (menu Atlas + entry New Atlas). +

+ +

+ Within this file a (large) number of tiles with its calibrated + coordinates are stored. AFTrack works best if each tile has got a + resolution of 256x256 Pixels. So uncheck Recreate/adjust map + tiles (CPU intensive). +

+

The output format is one file for each layer in the + corresponding folder.

+

+ Restrictions +

+

AFTrack can handle a maximum of 4096 tiles - so be sure not to + select more.

+ +

+ Google Earth Overlay (KMZ) +

+

+ For creating Google Earth Overlays you have to select Google + Earth Overlay (KMZ) as format in atlas format selection dialog that + appears when starting a new atlas (menu Atlas entry New + Atlas). +

+

Using this atlas output format the following features are + ignored when creating atlases:

+
    +
  • Recreate/adjust map tiles (custom tile size and image format)
  • +
+

Warning

+

+ The Google Earth Overlay atlas format uses JPG images. The image size + depends on the selected maximum map size (see settings dialog). The + theoretical maximum map size for this atlas format is 25000. However + it is strongly recommended not to set the maximum map size + higher than 10000 (this will result in a image with uncompressed size + about 286 MB). +

+ +

+ Creating Magellan RMP atlases +

+

+ For creating atlases of Creating Garmin Custom Maps you have to select + Magellan (RMP) as format in atlas format selection dialog that + appears when starting a new atlas (menu Atlas entry New + Atlas). +

+

Using this atlas output format the following features are + ignored when creating atlases:

+
    +
  • Recreate/adjust map tiles (custom tile size and image format)
  • +
+

Additionally some other limitations may apply, based on which + device and firmware version you are using. Mobile Atlas Creator does + not chek those limitations - therefore it may work or not if you are + using:

+
    +
  • An atlas with more than 5 maps.
  • +
  • Maps with a zoom level higher than 15.
  • +
+

+ The output format of an "atlas" for Magellan is one + RMP + file in the atlas directory. You can directly load this file in + Magellan VantagePoint or transfer it onto your device. +

+ +

+ Creating atlases for MAPLORER +

+

+ For creating atlases compatible with MAPLORER + you have to select the Maplorer atlas format as format in atlas + format selection dialog that appears when starting a new atlas (menu Atlas + entry New Atlas). You have to choose JPG image format + under Layer settings/tile format (PNG is not supported by + Maplorer). +

+ +

+ There are no specific limits on tile sizes and/or numbers; good + results for hiking/biking can be obtained using zoom level 15, custom + tile size of 1024x1024 (check Recreate/adjust map tiles (CPU + intensive) under Layer settings. For good performance, avoid + using too big or too many tiles (the maximum number of columns in + Maplorer is currently 26 ('A' to 'Z'), but it is preferable to use + less). +

+ +

+ After defining the maps and layers (select region and click Add + selection under Atlas Content) for the atlas, click the button + Create Atlas. Once atlas download and creation has completed, all + necessary files belonging to the atlas can be found in the directory + atlases\[atlas name]_[current date and time] + . +

+ +

+ To install the atlas on your device, simply connect it to your PC and + copy the content of the respective atlas subdirectory (i.e. all .jpg + and .pos files generated) to the Maplorer directory (the one which + contains maplorer.exe) on your device. Starting Maplorer on the device + will automatically read all tiles and create the index map. Detailed + instructions on making maps for Maplorer can be found at https://maplorer.com +

+ +

+ Creating and using atlases with Maverick +

+

+ For creating atlases compatible with Maverick you have to select Maverick + atlas format as format in atlas format selection dialog that appears + when starting a new atlas (menu Atlas entry New Atlas).
+ As atlases for Maverick do not support all features provided by Mobile + Atlas Creator the following settings are ignored when creating atlases + for AndNav: +

+
    +
  • Recreate/adjust map tiles (custom tile size and image format)
  • +
  • Name of all layers and maps
  • +
  • Structure of the atlas (which maps belongs to which layer)
  • +
+

+ For further information how to use offline atlases with Maverick + please see Maverick + Online Help on Setting up offline maps. +

+ +

+ Creating and using atlases with MGMaps +

+

+ For creating atlases compatible with MGMaps you have to select MGMaps + as format in atlas format selection dialog that appears when starting + a new atlas (menu Atlas entry New Atlas). Select a name + for the maps, this is important as you will use it to view the maps in + MGMaps. +

+

How to copy the maps to your device

+
    +
  1. Create a folder named MGMapsCache in the root of you + device or memorycard +
  2. +
  3. Copy the created folders into this MGMapsCache folder so the + directory structure looks like: +
  4. +
+
+MGMapsCache
+MGMapsCache\cache.conf
+MGMapsCache\macos_10
+MGMapsCache\macos_11
+MGMapsCache\macos_12
+MGMapsCache\macos_10\59_53.mgm
+MGMapsCache\macos_11\150_106.mgm
+MGMapsCache\macos_11\150_107.mgm
+MGMapsCache\macos_11\151_106.mgm
+MGMapsCache\macos_11\151_107.mgm
+MGMapsCache\macos_12\365_213.mgm
+MGMapsCache\macos_12\365_214.mgm
+MGMapsCache\macos_12\366_213.mgm
+MGMapsCache\macos_12\366_214.mgm
+	
+

How to set up MGMaps to use the maps

+
    +
  1. Select Settings/Map/Stored Maps, Click on the two boxes + labelled Stored Maps and Offline Mode. The first box enables the use + of stored map mode. The second box prohibits the use of the mobile + phones Internet connect to download live maps. You can leave this + unchecked if you want. stored maps folder: now tell MGMaps where you + have stored the map tile files. in my case SDCard/MGMapsCache. +
  2. +
  3. Select Settings/Map/Map types, select options/add custom + map,in map type name enter the name of the map you created using MAC + in my case macos, map type url you can leave blank, select + ok/options/save MGMaps will then apply the settings and display your + created map. +
  4. +
+

Warning

+

Avoid using names native to MGMaps such as google, each name + used must be defined as a custom map so the directory structure below + must have macos,macroad and macsat defined as custom map types.

+
+MGMapsCache MGMapsCache\cache.conf MGMapsCache\macos_10
+MGMapsCache\macos_11 MGMapsCache\macroad_11 MGMapsCache\macsat_11
+MGMapsCache\macos_12 MGMapsCache\macroad_12 MGMapsCache\macsat_12
+
+ +

+ Creating and using atlases with Mobile Trail + Explorer (MTE) +

+

+ For creating atlases compatible with Mobile Trail Explorer you have to + select Mobile Trail Explorer Cache as format in atlas format + selection dialog that appears when starting a new atlas (menu Atlas + entry New Atlas).
If a map source uses an image format + different to PNG the tiles will be automatically converted to the PNG + format.
The output is one + MTEFileCache + file per atlas which contains all maps. An existing cache file can not + be updated. If you want to add maps to an existing + MTEFileCache + please use the atlas format Mobile Trail Explorer which creates + a file structure identical to JTileDownloader and then process the + maps using MTE + CacheCreator.
As atlases for Mobile Trail Explorer does not + support all features provided by Mobile Atlas Creator the following + settings are ignored when creating atlases for Mobile Trail Explorer: +

+
    +
  • Recreate/adjust map tiles (custom tile size and image format)
  • +
  • Name of all layers and maps
  • +
  • Structure of the atlas (which maps belongs to which layer)
  • +
+ +

+ Creating atlases for NaviComputer +

+

+ For creating atlases, compatible with NaviComputer, you have to select + NaviComputer (NMAP) as format in atlas format selection dialog + that appears when starting a new atlas (menu Atlas entry New + Atlas).
After defining the maps and layers for the atlas to + be created, start atlas download and creation via the button Create + Atlas. Once download and creation has completed, the generated file + with the extension nmap can be found in the MOBAC output directory. + This *.nmap-file is the required input file for NaviComputer. +

+ +

+ Creating atlases for nfComPass +

+

+ For creating atlases, compatible with nfComPass, + you have to click Atlas -> New Atlas, select nfComPass + and give your Atlas a name.
By default atlases with a + tilesize of 64x64 are created (recommended). For different tile sizes + check Recreate/adjust map tiles (CPU intensive) under Layer + settings. Set Tileformat can not be changed - it is always png. Maybe + you must tryout, what is the best tilesize for your device. Choose + your layer and zoomlevels and click Add selection. Then click Create + atlas. Once download and creation has completed, the generated + folders can be found in the MOBAC output directory. You must copy the + data from the + nfComPass.dat + to your nfComPass.dat and fill in the path to your mapdirectory. After + that, copy the folder(s) to your device. If it is possible, you should + not copy the files with Active Sync to your device. +

+ +

+ Creating OruxMaps atlases +

+

+ For creating atlases compatible with OruxMaps + as format you have to select OruxMaps as format in atlas format + selection dialog that appears when starting a new atlas (menu Atlas + entry New Atlas). +

+

Using this atlas output format the following features are + ignored when creating atlases:

+
    +
  • Layer settings, custom tile size. OruxMaps always uses + 512x512 tile size. You can select the tile format (PNG or JPEG). If + you do not select any, default value is JPEG - quality 90. +
  • +
+

The output format of an "atlas" for OruxMaps is one or more map + directories in the atlas directory. You have to copy those maps onto + your device (default directory: /oruxmaps/mapfiles/).

+ +

+ Creating atlases for OSMAND +

+

+ For creating atlases compatible with OSMAND you have to select OSMAND + tile storage or OSMAND SQlite as format in atlas format + selection dialog that appears when starting a new atlas (menu Atlas + entry New Atlas).
As atlases for OSMAND do not support + all features provided by Mobile Atlas Creator the following settings + are ignored when creating atlases for OSMAND: +

+
    +
  • Change height or width of the map tiles
  • +
  • Name of all layers and maps
  • +
  • Structure of the atlas (which maps belongs to which layer)
  • +
+ +

+ Creating atlases for Osmdroid +

+

+ For creating atlases compatible with Osmdroid you have to select + either Osmdroid ZIP, Osmdroid SQLite or Osmdroid + GEMF as format in atlas format selection dialog that appears when + starting a new atlas (menu Atlas entry New Atlas).
+ The mentioned three formats are "single file" atlases. One + of the other possible atlas formats might also be acceptable for + Osmdroid. Also, there is other software that is able to deal with GEMF + archives.
As atlases for Osmdroid do not support all features + provided by Mobile Atlas Creator the following settings are ignored + when creating atlases for Osmdroid: +

+
    +
  • Change height or width of the map tiles
  • +
  • Name of all layers and maps
  • +
  • Structure of the atlas (which maps belongs to which layer)
  • +
+ +

+ Creating atlases for OSMTracker +

+

+ For creating atlases compatible with OSMTracker you have to select OSMTracker + tile storage as format in atlas format selection dialog that appears + when starting a new atlas (menu Atlas entry New Atlas).
+ As atlases for OSMTracker do not support all features provided by + Mobile Atlas Creator the following settings are ignored when creating + atlases for OSMTracker: +

+
    +
  • Change height or width of the map tiles
  • +
  • Name of all layers and maps
  • +
  • Structure of the atlas (which maps belongs to which layer)
  • +
+ +

+ Creating and using atlases with OziExplorer / large + PNG image export +

+

+ For creating atlases compatible with OziExplorer you have to select OziExplorer + (PNG & MAP) as format in atlas format selection dialog that + appears when starting a new atlas (menu Atlas entry New + Atlas). +

+

+ Restrictions +

+

As OziExplorer does not support tiled maps some features are + ignored when creating atlases in this format:

+
    +
  • Image output format is fix: 24bit PNG
  • +
  • Recreate/adjust map tiles custom tile is ignored
  • +
+

+ The output format of an "atlas" for OziExplorer is one subdirectory + per layer and within this subdirectory one + PNG + image and one + MAP + file per defined map. For opening a map in OziExplorer select the menu + FileLoad from FileLoad from MAP + file, browse to the layer directory of the created atlas and select + the MAP file. +

+

If you are only interested in the map image you can safely + delete the created map file.

+

+ Warning +

+

Mobile Atlas Creator uses a highly sophisticated and optimized + algorithm for creating the PNG files for OziExplorer use. This + algorithm allows to create very large maps images at low memory usage. + OziExplorer and most image viewers do not use such sophisticated + algorithms which can lead to the situation that you can create very + large map images - but OziExplorer and other image viewers are not + able to open the image.

+ +

+ Creating atlases for PathAway +

+

+ For creating atlases compatible with PathAway you have to select PathAway + tile cache as format in atlas format selection dialog that appears + when starting a new atlas (menu Atlas entry New Atlas). +
As atlases for PathAway do not support all features provided + by Mobile Atlas Creator the following restrictions apply when creating + atlases for PathAway: +

+
    +
  • The maximum zoom level is 16 - higher zoom levels are not + possible with this atlas format +
  • +
  • Tile width and width can not be changed (settings will be + ignored) +
  • +
  • Name of all layers and maps is ignored
  • +
  • Structure of the atlas is ignored (which maps belongs to + which layer) +
  • +
+ +

+ Creating and using atlases with RMaps +

+

+ For creating offline atlases compatible with RMaps + (Android application) you have to select RMaps SQLite as format + in atlas format selection dialog that appears when starting a new + atlas (menu Atlas entry New Atlas).
The atlas + format RMaps does not support all features provided by Mobile Atlas + Creator the following settings can not be used or are ignored when + creating atlases using this output format: +

+
    +
  • Recreate/adjust map tiles with custom tile size (height and + width have to be 256) +
  • +
  • Name of all layers and maps
  • +
  • Structure of the atlas (which maps belongs to which layer)
  • +
  • Atlases created after another are merged into one Database + named [AtlasName] atlas.sqlitedb which is located in the + atlas output directory. +
  • +
+ +

+ [Nokia] Sports Tracker +

+

+ For creating atlases compatible with Sports Tracker(ST) you have + to select Sports Tracker (NOT GPS Sportstracker) as format in + atlas format selection dialog that appears when starting a new atlas + (menu Atlas entry New Atlas). +

+

+ Do not select Recreate/adjust map tiles. +

+

Maximum Zoomlevel of Sports Tracker is 17, default is 13.

+

Copy the created atlas (the whole folder) into the following + folder of youre phone (depending of the Sports Tracker version):

+
    +
  • Sports Tracker 1.76: E:\system\data\Maps\Street\
  • +
  • Sports Tracker 2.x: E:\system\data\Maps\Street\
  • +
  • Sports Tracker 3.x: E:\system\data\STMaps\Street\
  • +
+

For changing the zoom level inside Storts Tracker press 5 to + zoom in and 0 to zoom out.

+ + +

+ Creating and using atlases with Touratech QV / + large PNG image export +

+

+ For creating atlases compatible with Touratech QV you have to select Touratech + QV as format in atlas format selection dialog that appears when + starting a new atlas (menu Atlas entry New Atlas). +

+

+ Restrictions +

+

As Touratech QV does not support tiled maps some features are + ignored when creating atlases in this format:

+
    +
  • Image output format is fix: 24bit PNG
  • +
  • Recreate/adjust map tiles custom tile is ignored
  • +
+

+ The output format of an "atlas" for Touratech QV is one subdirectory + per layer and within this subdirectory one + PNG + image and one + CAL + file per defined map. +

+

If you are only interested in the map image you can safely + delete the created cal file.

+

+ Warning +

+

Mobile Atlas Creator uses a highly sophisticated and optimized + algorithm for creating the PNG files for Touratech QV use. This + algorithm allows to create very large maps images at low memory usage. + Touratech QV and most image viewers do not use such sophisticated + algorithms which can lead to the situation that you can create very + large map images - but Touratech QV and other image viewers are not + able to open the image.

+ +

+ Creating atlases using TomTom Raster format +

+

TBD

+ +

+ Creating and using atlases with TrekBuddy +

+

+ For creating atlases compatible with TrekBuddy you have to select TrekBuddy + tared atlas or TrekBuddy untared atlas as format in atlas + format selection dialog that appears when starting a new atlas (menu Atlas + entry New Atlas). +

+

+ After defining the maps and layers for the atlas to be created start + atlas download and creation via the button Create Atlas. Once + atlas download and creation has completed all necessary files + belonging to the atlas can be found in the directory + atlases\[atlas name]_[current date and time] + . +

+

+ The atlas itself consists of the atlas startup file + cr.tar + (tar format) or + cr.tba + (regular/untared format) and the subdirectories containing the + different maps of the atlas. For using the atlas with TrekBuddy copy + the whole directory onto your J2ME device. Then use the Load + Atlas function of TrekBuddy and open + cr.tar + / + cr.tba + (in the atlas root directory). +

+ +

+ Creating and using atlases with TwoNav & + CompeGPS Land/Air +

+

+ To create atlases compatible with TwoNav software you have to select TwoNav + (RMAP) as format in atlas format selection dialog that appears when + starting a new atlas (menu Atlas entry New Atlas). + Atlases created for TwoNav are stored in a format called rmap. It's a + binary format that holds the same map data stored at different + resolutions - in order to make zooming in and out on low performance + mobile devices fast and efficient. However, this causes some + restrictions which have to be taken into account: +

+
    +
  • Each map within a layer has to have the same geographical + bounds. +
  • +
  • There only can be one map in a layer with a given zoom level
  • +
+

If there are several layers in one atlas, each layer will be + stored as a separate rmap file.

+

The easiest way to create a correct atlas content is: first + select the appropriate grid zoom (combobox next to the zoom slider), + then pick zoom levels from the selected grid zoom up to the zoom level + of the desired most detailed level, and finally add a selection to the + Atlas content by clicking on the "Add selection" button.

+

Rmap format also requires no gaps in a zoom level range from the + maximum to the minimum selected zoom level. If there are missing zoom + levels, they will be created internally by shrinking the existing + downloaded tiles. If the missing zoom levels contain a lot of tiles, + this operation could take a while.

+

+ Finally copy the + layer.rmap + file from the + atlases\[atlas name]_[current date and time] + folder to your TwoNav + maps + folder. +

+

As TwoNav does not support all available features provided my + MOBAC, some features can not be used when creating atlases in this + format:

+
    +
  • Custom tile height and width (is ignored for TwoNav RMP + atlases) +
  • +
  • Custom tile format: Only JPEG formats are allowed
  • +
+ +

+ Creating and using atlases with Viewranger +

+

+ For creating atlases compatible with Viewranger(VR) you have to + select Viewranger as format in atlas format selection dialog + that appears when starting a new atlas (menu Atlas entry New + Atlas). +

+

Maximum Zoomlevel of Viewranger is 18, minimum is 3.

+

After creating your atlas the folder structure looks like:

+
    +
  • Mobile Atlas Creator + 1.9\atlases\VR_2012-03-28_154944\OSM\13\4308
  • +
  • Mobile Atlas Creator + 1.9\atlases\VR_2012-03-28_154944\OSM\14\43
  • +
  • Mobile Atlas Creator + 1.9\atlases\VR_2012-03-28_154944\google\13\4308
  • +
  • Mobile Atlas Creator + 1.9\atlases\VR_2012-03-28_154944\google\14\43
  • +
+

+ Now we have to + Create a Folder Structure on the Device: +

+

+ If you youre VR Folder is on E: it is on Symbian located in + E:/ViewRanger/MapCache/_PAlbTN/ +

+

In this folder create following Subfolders, if not already + present:

+

84,85,87,88,89,129

+

+ e.g. + /ViewRanger/MapCache/_PAlbTN/84 +

+

Copy the content of "OSM" into 84, "google" into 85 and so on.

+

+ Now it looks like: + E:/ViewRanger/MapCache/_PAlbTN/13/4308/2687 + , 2687 is a tile +

+

VR has different Online Mapsources which are assigned to the + Numbers as shown:

+ +
    +
  • OSM->84
  • +
  • Opencyclemap->85
  • +
  • OSM Direct->87
  • +
  • OSM Midnigth->88
  • +
  • OSM Fresh->89
  • +
  • Open Piste Map->129
  • +
+ +

Of course you can fill the Tilecache with different Maps.

+

I use the Open Piste Map eg. as "OSM Public Transport"

+ + +

+ Enhancement requests +

+

+ If you are missing the map provider of your choice or have other + enhancement ideas for Mobile Atlas Creator feel free to open an Feature + Request Ticket at SourceForge. +

+ + +

+ Problems, Bugs & Errors +

+

+ In case of unexpected errors while executing Mobile Atlas Creator you + may get presented a exception dialog containing detailed information + about the problem. In such a case please create a new ticket + in the Bug Tracker at SourceForge. Please add the detailed exception + information and a detailed description of your last performed actions. +

+ +

The default error log

+

+ By default Mobile Atlas Creator records all errors of the current + session into it's error log file + Mobile Atlas Creator.log + . This log file is located on Windows system in the directory + %APPDATA%\Mobile Atlas Creator\ + and on Linux/Unix/OSX system in the directory + ~/.mobac/ +

+ +

Activate the advanced logging system

+

+ If the recorded errors in the error log do not indicate a problem you can activate the overall message logging + mechanism of Mobile Atlas Creator. + The next start Mobile Atlas Creator will create a log file in the + current directory (on Windows this is usually the directory where the + JAR file is located on Linux usually the profile directory). Please + note that the log file is erased on each program start. + If you think you have found a bug please file it in the + bug tracker at SourceForge. +

+

MOBAC 2.2.2 and newer

+

+ Download the file logback.xml and save it in the directory + where the jar file of Mobile Atlas Creator is installed to. +

+

MOBAC 2.2.1 and older

+

+ Download the file log4j.xml and save it in the directory + where the jar file of Mobile Atlas Creator is installed to. +

+ + +

+ Known problems and limitations +

+

New map sources

+

+ Mobile Atlas Creator is limited to map sources that provide their maps + if form of map tiles. Each of that map tiles has to be of size 256x256 + pixels. Additionally the map source has to use the spherical Mercator + projection and the number of tiles forming the world on each zoom + level has to be one of the following values: 20, 21, + 22 ... 221, 222.
For more + details see OpenStreetMap Wiki: Slippy + map tilenames, Mercator, + Height + and width of a map and Zoom levels +

+

Java Bugs

+

Due to bugs in Java you should not do the following:

+
    +
  • Install Mobile Atlas Creator into a directory which path contains an "!" (exclamation mark) because of this + Oracle Java bug +
  • +
  • Do not use OpenJDK if you want to work with GPX tracks in + Mobile Atlas Creator +
  • +
  • On Windows without a system proxy set (see connection + settings of IE) it is strongly recommended not to use the + following proxy setting:Use standard Java proxy settings +
+ + +

+ Details for advanced users +

+

+ Specifying directory configuration +

+

The following steps are necessary if MOBAC is installed to to a + directory that is not writable for regular users:

+

+ For changing the directory configuration pattern for all users of a + MOBAC installation save this + file into the same directory where Mobile_Atlas_Creator.jar + has been installed into and change it's name to directories.ini. + For more details read the comments in this configuration file. +

+ +

+ Moving the tile store directory +

+

+ Usually the tile store directory where Mobile Atlas Creator saves all + downloaded images in is automatically determined.
In case you + want to select a different directory perform the following steps: +

+
    +
  1. Make sure you have closed MOBAC
  2. +
  3. Open settings.xml in an text editor +
  4. +
  5. Inside of the tag <settings> search for the + tag <directories>. Inside this tag create a new tag + named <tileStoreDirectory>
  6. +
  7. Set the path name to the value of this tag (Windows users + should replace backslashes with a slashes) +
  8. +
  9. (optional) Copy or move the content of the old tile store + directory into the new tile store directory. +
  10. +
+

Example

+
+<settings>
+    <directories>
+        <tileStoreDirectory>E:/tiles</tileStoreDirectory>
+    </directories>
+    ...
+</settings>
+

+ This specified the windows directory + E:\tiles + as new tile store directory. The previously used tile store will not + be used anymore.
Deleting the + <tileStoreDirectory> + tag restores the old behavior (automatically tile store directory + selection). +

+ +

+ Starting external tools from within MOBAC +

+ +

+ External tools like scripts or other executable programs can be + started from the Tools menu from within MOBAC. This menu is + only visible if external programs have been configured. The advantage + of starting a program from within MOBAC is that certain information + about selected map source, selected region ... can be transmitted as + parameters to the executed program.
This allows you for + example to create your own maps (render tiles) with external tools + like OSMFILTER, + OSMCONVERT, + MAPERITIVE... +

+

+ For defining an external program, create an xml file for each external + program to be called. The content of the xml file has to be like one + of the following examples. The file-name of the xml is not relevant - + it only has to end with + .xml +

test.xml

+

Demonstrates how to execute an Windows batch file.

+
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<ExternalTool>
+ <name>Name shown in tools menu</name>
+ <command>cmd.exe /c start .\tools\mybatch.cmd</command>
+ <parameters>MIN_LON MIN_LAT MAX_LON MAX_LAT MIN_ZOOM MAX_ZOOM MAPSOURCE_NAME MAPSOURCE_DISPLAYNAME NAME_EDITBOX </parameters>
+ <debug>true</debug>
+</ExternalTool>
+
+

+ Annotated sample file download +

+ +

test-exe.xml

+

Demonstrates how to execute an regular windows program.

+
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<ExternalTool>
+ <name>Name shown in tools menu</name>
+ <command>C:\sample-path\program.exe</command>
+ <parameters>MIN_LON MIN_LAT MAX_LON MAX_LAT MIN_ZOOM MAX_ZOOM MAPSOURCE_NAME MAPSOURCE_DISPLAYNAME NAME_EDITBOX </parameters>
+ <debug>true</debug>
+</ExternalTool>
+
+ +

+ The most interesting section is the content of <parameters>. + It contains a space separated list of parameters the specified command + will be executed with. The following values can be used: +

    +
  • MAX_LAT - Maximum latitude (upper border) off the + selected area +
  • +
  • MIN_LAT - Minimum latitude (lower border) off the + selected area +
  • +
  • MAX_LON - Maximum longitude (right border) off the + selected area +
  • +
  • MIN_LON - Minimum longitude (left border) off the + selected area +
  • +
  • MIN_ZOOM - minimum zoom of selected zoom levels + check-boxes +
  • +
  • MAX_ZOOM - maximum zoom of selected zoom levels + check-boxes +
  • +
  • MAPSOURCE_NAME - Currently select map source + internal name (used in atlas profile xml file) +
  • +
  • MAPSOURCE_DISPLAYNAME - Currently select map source + display name (as shown in the GUI) +
  • +
  • NAME_EDITBOX - content of the edit box "Name" in the + side panel "Atlas Content" +
+ + + +

+ Custom map sources +

+

+ Simple custom map sources +

+

+ Custom map sources which uses a similar URL scheme as + Google/OpenStreetMap can be added by saving for each custom map source + the definition in form of an xml file in the + mapsources + directory. +

+

The following section shows is an example how the xml file has + to be formatted. It defines an additional map source named "Custom OSM + Mapnik" which shows map tiles identical to the predefined map source + "OpenStreetMap Mapnik".

+

+ Note:The name specified in + there has to be unique among all available map sources within MOBAC. + The list of all available map sources can be obtained via command Show + all map source names in the menu Debug. +

+
+<?xml version="1.0" encoding="UTF-8"?>
+<customMapSource>
+	<name>Custom OSM Mapnik</name>
+	<minZoom>0</minZoom>
+	<maxZoom>18</maxZoom>
+	<tileType>png</tileType>
+	<tileUpdate>None</tileUpdate>
+	<url>https://tile.openstreetmap.org/{$z}/{$x}/{$y}.png</url>
+	<backgroundColor>#000000</backgroundColor>
+</customMapSource>
+
+

The most important part of this definition is the url. It is a + template containing specific placeholders which are encapsulated by + curly brace:

+
    +
  • {$z} for the zoom level - number range: [minZoom + .. maxZoom] +
  • +
  • {$x} for the x tile coordinate - number range: [0..2zoom + level ] +
  • +
  • {$y} for the y tile coordinate - number range: [0..2zoom + level ] +
  • +
+

+ Note: If the url contains the ampersand character & you + have to encode it as &amp;. Otherwise it not be valid XML + and therefore can not bo loaded by MOBAC. +

+

+ Example file for download: + Example custom map source.xml +

+

+ Custom WMS map sources +

+

+ Similar a WMS map source can be defined. Currently only + 1.1.1 and 1.3.0 + as version are supported. +

+

+ Tag coordinateunit is used to separate EPSG:4326, EPSG:4171 (unit in degree by default) + from EPSG:3857, EPSG:900913 + and EPSG:3785 (unit in meter) +

+

+ EPSG:4326, EPSG:4171 (unit in degree by default) +

+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<customWmsMapSource>
+    <name>TerraServer WMS</name>
+    <minZoom>12</minZoom>
+    <maxZoom>18</maxZoom>
+    <tileType>JPG</tileType>
+    <version>1.1.1</version>
+    <layers>DRG</layers>
+    <url>http://terraserver-usa.com/ogcmap6.ashx?</url>
+    <coordinatesystem>EPSG:4326</coordinatesystem>
+    <!-- optional, by default "degree" -->
+    <coordinateunit>degree</coordinateunit>
+    <aditionalparameters>&amp;EXCEPTIONS=BLANK&amp;Styles=</aditionalparameters>
+    <backgroundColor>#000000</backgroundColor>
+</customWmsMapSource>
+

+ Example file (with comments) for download: + Example custom WMS map source.xml +

+

+ EPSG:3857, EPSG:900913 and EPSG:3785 (unit in meter) +

+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<customWmsMapSource>
+    <name>Modele, XML WMS 1.3.0-meters(France)</name>
+    <minZoom>6</minZoom>
+    <maxZoom>18</maxZoom>
+    <tileType>PNG</tileType>
+    <version>1.3.0</version>
+    <layers>BassinDCE_FXX,SsBassinDCEAdmin_FXX</layers>
+    <url>https://services.sandre.eaufrance.fr/geo/mdo?</url>
+    <coordinatesystem>EPSG:3857</coordinatesystem>
+    <!-- required -->
+    <coordinateunit>meter</coordinateunit>
+</customWmsMapSource>
+

+ Example file (with comments) for download: + Example custom WMS map source in meter.xml +

+

+ Custom multi-layer map sources +

+

+ The same way as custom map sources map + sources which consist of two or more layers can be defined as well. + Note that all except the background map source layer (first in the + list) must have transparent parts - otherwise layers in the list + before will not be visible. +

+
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<customMultiLayerMapSource>
+    <name>Custom OSM Mapnik with Hills (Ger)</name>
+    <tileType>PNG</tileType>
+    <backgroundColor>#000000</backgroundColor>
+    <layers>
+        <customMapSource>
+            <name>Custom OSM Mapnik</name>
+            <minZoom>0</minZoom>
+            <maxZoom>18</maxZoom>
+            <tileType>PNG</tileType>
+            <tileUpdate>None</tileUpdate>
+            <url>https://tile.openstreetmap.org/{$z}/{$x}/{$y}.png</url>
+        </customMapSource>
+        <customMapSource>
+            <name>Custom transparent hillshade</name>
+            <minZoom>0</minZoom>
+            <maxZoom>18</maxZoom>
+            <tileType>PNG</tileType>
+            <tileUpdate>None</tileUpdate>
+            <url>https://www.wanderreitkarte.de/hills/{$z}/{$x}/{$y}.png</url>
+        </customMapSource>
+    </layers>
+</customMultiLayerMapSource>
+
+

+ Example file for download: + Example custom multi-layer map source.xml +

+

+ Custom BeanShell map sources +

+

+ BeanShell map sources as the can be developed using MapEvaluator + can be used by MOBAC. To do so place the saved BeanShell code file + (file extension .bsh) in the mapsources + directory. It will be loaded on next start-up of MOBAC. +

+

+ It is recommended to add a line defining the map source name (must be unique). +

+
name = "Your map source name here";
+

+ Example file for download: + Example beanshell map source.bsh +

+ +

+ Custom Map Pack +

+

+ Developing a custom map pack requires at least basic Java skills. + Therefore the description on how to develop a custom map pack is only + part of the source code release of MOBAC. You can get the source code + of MOBAC by using the latest src release available in the + files section at Sourceforge + or you can get it directly from the + Subversion code repository + using the latest trunk version. +

+

+ MOBAC integrated rendering of tiles based on + OpenStreetmap (mapsforge) vector data +

+

+ Since version 2.0 MOBAC includes the + mapsforge rendering + engine. This allows MOBAC to render bitmap tiles on-the-fly using + Mapsforge vector data files. Those vector data files can be downloaded + pre-generated for a large number of regions world-wide. Alternatively + you can convert OpenStreetMap data to mapsforge format on your own. + The map rendering of the vector data can be configured using xml + base render themes. +

+

For using mapsforge vector data within MOBAC the following steps + are required:

+
    +
  1. Download or + create a mapsforge vector data file and save it on your compurter +
  2. +
  3. Create a custom XML map source file in the mapsources + subdirectory similar to the example file. +
    +<?xml version="1.0" encoding="UTF-8"?>
    +<mapsforge>
    +	<!-- name of the map - as shown in map source list -->
    +	<name>Custom Mapsforge</name>
    +	
    +	<!-- optional -->
    +	<minZoom>0</minZoom> 
    +	
    +	<!-- optional -->
    +	<maxZoom>20</maxZoom> 
    +	    
    +	<!-- absolute or relative file name -->
    +	<mapFile>mapsforge-test.map</mapFile>
    +	
    +	<!-- optional default OSMARENDERER Theme -->
    +	<!-- <xmlRenderTheme>mytheme.xml</xmlRenderTheme> -->
    +	
    +	<transparent>false</transparent>
    +	
    +	<!-- text size scale factor -->
    +	<textScale>1.0</textScale>
    +	
    +</mapsforge>
    +
    +
  4. +
  5. Start or Restart MOBAC
  6. +
+ +

+ Custom atlas as map source / locally generated + tiles +

+

+ Existing atlases or locally rendered tiles can be directly integrated + into MOBAC as custom map source without having to set-up a local + web-server.
At the moment the formats used by OSMTracker, + AndNav, Maverick and OSMAND are supported. For adding such an atlas as + map source download the Example + custom tile files source.xml file, adapt the + <sourceFolder> + entry and place it in the + mapsources + directory. +

+

+ Tiles can also be packed into one or more zip files and directly used + by MOBAC. For details please see the Example + custom tile zip source.xml.
Note: When working with + large ZIP files (more than 4 GB) it is required to use Java 7. +

+

+ SQLite based atlas formats (RMaps, MBTiles, BigPlanetTracks, + NaviComputer or OSMAND) can also be used directly by MOBAC. For + details please see the Example + custom tile SQLite source.xml +

+ + \ No newline at end of file diff --git a/README.md b/README.md index 05e9de4..2b05706 100644 --- a/README.md +++ b/README.md @@ -1,729 +1,18 @@ -# Mobile Atlas Creator UNLOCKED +# mobac-unlocked -I modified MOBAC to do some things: -* Increased tile limit to 1 million (should be more than enough for 99% of applications) -* Added the default open street map server (doesn't work) -* Included SQLite driver by default -* Removed some broken mapsources +*MOBAC with an increased tile limit and questionable map sources.* -Right now, this is MOBAC version 1.9.16. +I modified MOBAC to do some special things: -# Original Readme +- Increased tile limit to 2 million. +- Added a few "questionable" map sources. -Welcome to Mobile Atlas Creator read-me file for end users. +## Original README -Before January 2010 this project was known as "TrekBuddy Atlas Creator". +[README.html](https://git.evulid.cc/cyberes/mobac-unlocked/src/branch/master/README.html) -Mobile Atlas Creator is an open source project hosted on SourceForge.net: -[http://mobac.sf.net](http://mobac.sf.net) +## Build -## Table of contents - -* [License](#License) -* [Description](#Description) -* [Requirements](#Requirements) - * [Java Advanced Imaging" (JAI)](#JAI) -* [Installation](#Installation) -* [Application start](#Start) -* [The different atlas formats](#AtlasFormats) - * [AFTrack (OSZ)](#AFTrackOSZ) - * [AlpineQuestMap (AQM)](#AlpineQuestMap) - * [AndNav](#AndNav) - * [Big Planet Tracks](#BigPlanet) - * [CacheWolf](#CacheWolf) - * [Garmin Custom maps](#GarminCustom) - * [Glopus](#Glopus) - * [Glopus Map File / AFTrack (GMF)](#GMF) - * [Google Earth Overlay (KMZ)](#KMZ) - * [Magellan RMP](#Magellan) - * [MAPLORER](#MAPLORER) - * [Maverick](#Maverick) - * [MGMaps](#MGMaps) - * [Mobile Trail Explorer (MTE)](#MTE) - * [NaviComputer](#NaviComputer) - * [nfComPass](#nfComPass) - * [OruxMaps](#OruxMaps) - * [OSMAND](#OSMAND) - * [Osmdroid](#Osmdroid) - * [OSMTracker](#OSMTracker) - * [OziExplorer / large PNG image](#Ozi) - * [PathAway](#PathAway) - * [RMaps](#RMaps) - * [[Nokia] Sports Tracker](#SportsTracker) - * [TomTom Raster](#TomTomRaster) - * [Touratech QV](#TTQV) - * [TrekBuddy](#TrekBuddy) - * [TwoNav (RMAP)](#TwoNav) - * [Viewranger](#Viewranger) -* [Enhancement requests](#Enhancement) -* [Problems, Bugs & Errors](#Bugs) -* [Known problems and limitations](#Limitations) -* [Details for advanced users](#AdvancedUsers) - * [Specifying directory configuration](#DirectoryConfig) - * [Moving the tile store directory](#TileStoreDir) - * [Starting external tools from within MOBAC](#ExternalTools) -* [Custom map sources](#CustomMapSource) - * [Simple custom map sources](#SimpleCustomMapSource) - * [Custom WMS map sources](#CustomWMSMapSource) - * [Custom multi-layer map sources](#CustomMultiLayerMapSource) - * [Custom CloudMade map sources](#CloudMadeMapSource) - * [Custom BeanShell map sources](#BeanShellMapSource) - * [Custom MapPack](#CustomMapPack) - * [Custom atlas as map source / locally generated tiles](#FileBased) - -* * * - -## License - -Mobile Atlas Creator is under GNU General Public License Version 2 (GPL). For details on the GPL see the license file [gpl.txt](gpl.txt). -The source code is available on the [SourceForge.net](http://sourceforge.net/projects/mobac/files/) for download and in the [project's source code Subversion repository](http://sourceforge.net/p/mobac/code/). - -## Description - -Mobile Atlas Creator creates atlases for several applications. For example [TrekBuddy](http://www.trekbuddy.net) and [Mobile Trail Explorer (MTE)](http://code.google.com/p/mobile-trail-explorer/), the Android applications [AndNav](http://www.andnav.org/), [Maverick](http://www.codesector.com/maverick.php), [Big Planet Tracks](http://code.google.com/p/big-planet-tracks/), [RMaps](http://robertdeveloper.blogspot.com/search/label/rmaps.release), [OruxMaps](http://www.oruxmaps.com/), the Pocket PC application [Glopus](http://www.glopus.de/) and the commercial Windows application [OziExplorer](http://www.oziexplorer.com/). The map image created for OziExplorer can also be used with any PNG capable image viewer (map image in one large PNG file). - -## Requirements - -This application requires that a Java Runtime Environment Version 6 Update 14 (v1.6.0_14) or higher is installed on the computer. - -If you have the choice between different Java Runtimes you should prefer the Java Runtime provided by Sun/Oracle. Especially the OpenJDK has some bugs regarding MOBAC and tends to crash on certain situations. - -### Java Advanced Imaging (optional) - -For reducing the color depth of downloaded tiles the library files ( jai_core.jar and jai_codec.jar ) of the "Java Advanced Imaging" (JAI) have to be present on the system respectively in the same directory as Mobile_Atlas_Creator.jar. Ready to use binary builds of the Java Advanced Imaging library can be obtained at [http://download.java.net/media/jai/builds/release/1_1_3/jai-1_1_3-lib.zip](http://download.java.net/media/jai/builds/release/1_1_3/jai-1_1_3-lib.zip) - -## Installation - -Copy or move the unzipped files to a folder where you would like to have Mobile Atlas Creator installed. On computers running Windows please make sure **not to install MOBAC into Program Files sub-directory!** - -## Application start - -### Windows - -The application is started by executing the Mobile Atlas Creator.exe . During the first application start all necessary files and folders are automatically created by the application. - -### Linux and OSX - -You can start MOBAC by executing the start-up script start.sh . Before starting MOBAC the first time it may be necessary to set the executable bit for start.sh e.g. by executing the following command: - -
chmod u+x start.sh
- -During the first application start all necessary files and folders are automatically created by the application. - -* * * - -## The different atlas formats - -### AFTrack OSZ - -For creating atlases compatible with AFTrack (Symbian S60) you have to select **AFTrack (OSZ)** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). - -OSZ is a ZIP-archive. Within this zip archive a (large) number of tiles with the calibrated folder structure (coordinates) are stored. OSZ only works if each tile has got a resolution of 256x256 Pixels. So be sure to uncheck **Recreate/adjust map tiles (CPU intensive)**. - -The output format is one file for each layer in the corresponding folder. - -#### Restrictions - -Depending on the device free memory the file maybe not work. So more then 80000 tiles should not be used. - -### AlpineQuestMap (AQM) - -Sorry no further details are available for this atlas format. - -### Creating and using atlases with AndNav - -For creating atlases compatible with AndNav you have to select **AndNav atlas format** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). -As atlases for AndNav do not support all features provided by Mobile Atlas Creator the following settings are ignored when creating atlases for AndNav: - -* Change height or width of the map tiles -* Name of all layers and maps -* Structure of the atlas (which maps belongs to which layer) - -### Creating and using atlases with Big Planet Tracks - -For creating offline atlases compatible with [Big Planet Tracks](http://code.google.com/p/big-planet-tracks/) (Android application) you have to select **Big Planet Tracks SQLite** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). -The atlas format BigPlanet SQLite does not support all features provided by Mobile Atlas Creator the following settings can not be used or are ignored when creating atlases using this output format: - -* Recreate/adjust map tiles with custom tile size (height and -* Name of all layers and maps -* Structure of the atlas (which maps belongs to which layer) -* Atlases created after another are merged into one Database named [Atlasname] atlas.sqlitedb which is located in the atlas output directory. - -### Creating atlases for CacheWolf - -For creating atlases compatible with [CacheWolf](http://www.cachewolf.de) you have to select **CacheWolf WFL** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). - -#### Custom tile processing settings enabled - -Maps that have custom tile processing options set are saved as tiled images with one WFL calibration file for each tile. All processing options such as image format and tile size can be used. - -#### Custom tile processing settings disabled - -In this mode automatic tiling is disabled and the same [restrictions](#OziRestriction) and the [warning](#OziWarning) as for the OziExplorer output format apply. - -The output format of an "atlas" for CacheWolf is one subdirectory per layer and within this subdirectory one PNG image and one WFL file per defined map. - -### Creating Garmin Custom maps - -For creating atlases of Creating Garmin Custom maps you have to select **Garmin Custom Map (KMZ)** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). -Details about the Garmin Custom Map format can be found in the [Garmin Forums](https://forums.garmin.com/forumdisplay.php?f=205) - -Using this atlas output format the following features are ignored when creating atlases: - -* Recreate/adjust map tiles (custom tile size and image format) - -The output format of an "atlas" for Garmin Custom maps is one KMZ file per layer containing all maps (max 100) as seperate JPG image files. The JPEG compression rate can be specified for each map/image using image format selector in the custom tile processing section. The Garmin Custom Map format defines a maximum image size of 1024x1024 pixels. If a map is larger it will be automatically scaled down to fit into this size. You can prevent scaling when setting the max map size in the settings dialog to 1024. - -### Creating atlases for Glopus - -For creating atlases compatible with Glopus you have to select **Glopus (PNG & KAL)** or **Glopus Map File (GMF)** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). - -#### Glopus (PNG & KAL) - -Using this atlas output format the same [restrictions](#OziRestriction) and the [warning](#OziWarning) as for the OziExplorer output format apply. - -The output format of an "atlas" for Glopus is one subdirectory per layer and within this subdirectory one PNG image and one KAL file per defined map. - -#### Glopus Map File (GMF) - -Within this file a (large) number of tiles with its calibrated coordinates are stored. Glopus works best if each tile has a resolution of 1024x1024 pixels. So check **Recreate/adjust map tiles (CPU intensive)**. Width and height should be set to **1024**. - -The output format is one file for each layer in the corresponding folder. - -### Glopus Map File (GMF) / AFTrack - -For creating atlases compatible with AFTrack (Symbian S60) you have to select **Glopus Map File (GMF)** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). - -Within this file a (large) number of tiles with its calibrated coordinates are stored. AFTrack works best if each tile has got a resolution of 256x256 Pixels. So uncheck **Recreate/adjust map tiles (CPU intensive)**. - -The output format is one file for each layer in the corresponding folder. - -#### Restrictions - -AFTrack can handle a maximum of 4096 tiles - so be sure not to select more. - -### Google Earth Overlay (KMZ) - -For creating Google Earth Overlays you have to select **Google Earth Overlay (KMZ)** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). - -Using this atlas output format the following features are ignored when creating atlases: - -* Recreate/adjust map tiles (custom tile size and image format) - -#### Warning - -The Google Earth Overlay atlas format uses JPG images. The image size depends on the selected maximum map size (see settings dialog). The theoretical maximum map size for this atlas format is 25000\. However it is **strongly recommended not to set the maximum map size higher than 10000** (this will result in a image with uncompressed size about 286 MB). - -### Creating Magellan RMP atlases - -For creating atlases of Creating Garmin Custom Maps you have to select **Magellan (RMP)** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). - -Using this atlas output format the following features are ignored when creating atlases: - -* Recreate/adjust map tiles (custom tile size and image format) - -Additionally some other limitations may apply, based on which device and firmware version you are using. Mobile Atlas Creator does not chek those limitations - therefore it may work or not if you are using: - -* An atlas with more than 5 maps. -* Maps with a zoom level higher than 15. - -The output format of an "atlas" for Magellan is one RMP file in the atlas directory. You can directly load this file in Magellan VantagePoint or transfer it onto your device. - -### Creating atlases for MAPLORER - -For creating atlases compatible with [MAPLORER](http://maplorer.com) you have to select the **Maplorer atlas format** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). You have to choose **JPG image format** under **Layer settings/tile format** (PNG is not supported by Maplorer). - -There are no specific limits on tile sizes and/or numbers; good results for hiking/biking can be obtained using zoom level 15, custom tile size of 1024x1024 (check **Recreate/adjust map tiles (CPU intensive)** under **Layer settings**. For good performance, avoid using too big or too many tiles (the maximum number of columns in Maplorer is currently 26 ('A' to 'Z'), but it is preferable to use less). - -After defining the maps and layers (select region and click **Add selection** under **Atlas Content)** for the atlas, click the button Create Atlas. Once atlas download and creation has completed, all necessary files belonging to the atlas can be found in the directory atlases\[atlas name]_[current date and time] . - -To install the atlas on your device, simply connect it to your PC and copy the content of the respective atlas subdirectory (i.e. all .jpg and .pos files generated) to the Maplorer directory (the one which contains maplorer.exe) on your device. Starting Maplorer on the device will automatically read all tiles and create the index map. Detailed instructions on making maps for Maplorer can be found at [http://maplorer.com](http://maplorer.com) - -### Creating and using atlases with Maverick - -For creating atlases compatible with Maverick you have to select **Maverick atlas format** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). -As atlases for Maverick do not support all features provided by Mobile Atlas Creator the following settings are ignored when creating atlases for AndNav: - -* Recreate/adjust map tiles (custom tile size and image format) -* Name of all layers and maps -* Structure of the atlas (which maps belongs to which layer) - -For further information how to use offline atlases with Maverick please see [Maverick Online Help on Setting up offline maps](http://help.codesector.com/MapsCache). - -### Creating and using atlases with MGMaps - -For creating atlases compatible with MGMaps you have to select **MGMaps** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). Select a name for the maps, this is important as you will use it to view the maps in MGMaps. - -#### How to copy the maps to your device - -1. Create a folder named MGMapsCache in the root of you device or memorycard -2. Copy the created folders into this MGMapsCache folder so the directory structure looks like: - -
MGMapsCache
-MGMapsCache\cache.conf
-MGMapsCache\macos_10
-MGMapsCache\macos_11
-MGMapsCache\macos_12
-MGMapsCache\macos_10\59_53.mgm
-MGMapsCache\macos_11\150_106.mgm
-MGMapsCache\macos_11\150_107.mgm
-MGMapsCache\macos_11\151_106.mgm
-MGMapsCache\macos_11\151_107.mgm
-MGMapsCache\macos_12\365_213.mgm
-MGMapsCache\macos_12\365_214.mgm
-MGMapsCache\macos_12\366_213.mgm
-MGMapsCache\macos_12\366_214.mgm
-	
- -#### How to set up MGMaps to use the maps - -1. Select Settings/Map/Stored Maps, Click on the two boxes labelled Stored Maps and Offline Mode. The first box enables the use of stored map mode. The second box prohibits the use of the mobile phones Internet connect to download live maps. You can leave this unchecked if you want. stored maps folder: now tell MGMaps where you have stored the map tile files. in my case SDCard/MGMapsCache. -2. Select Settings/Map/Map types, select options/add custom map,in map type name enter the name of the map you created using MAC in my case macos, map type url you can leave blank, select ok/options/save MGMaps will then apply the settings and display your created map. - -#### Warning - -Avoid using names native to MGMaps such as google, each name used must be defined as a custom map so the directory structure below must have macos,macroad and macsat defined as custom map types. - -
MGMapsCache MGMapsCache\cache.conf MGMapsCache\macos_10
-MGMapsCache\macos_11 MGMapsCache\macroad_11 MGMapsCache\macsat_11
-MGMapsCache\macos_12 MGMapsCache\macroad_12 MGMapsCache\macsat_12
-
- -### Creating and using atlases with Mobile Trail Explorer (MTE) - -For creating atlases compatible with Mobile Trail Explorer you have to select **Mobile Trail Explorer Cache** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). -If a map source uses an image format different to PNG the tiles will be automatically converted to the PNG format. -The output is one MTEFileCache file per atlas which contains all maps. An existing cache file can not be updated. If you want to add maps to an existing MTEFileCache please use the atlas format **Mobile Trail Explorer** which creates a file structure identical to JTileDownloader and then process the maps using [MTE CacheCreator](http://code.google.com/p/mobile-trail-explorer/wiki/CacheCreator). -As atlases for Mobile Trail Explorer does not support all features provided by Mobile Atlas Creator the following settings are ignored when creating atlases for Mobile Trail Explorer: - -* Recreate/adjust map tiles (custom tile size and image format) -* Name of all layers and maps -* Structure of the atlas (which maps belongs to which layer) - -### Creating atlases for NaviComputer - -For creating atlases, compatible with NaviComputer, you have to select **NaviComputer (NMAP)** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). -After defining the maps and layers for the atlas to be created, start atlas download and creation via the button **Create Atlas**. Once download and creation has completed, the generated file with the extension nmap can be found in the MOBAC output directory. This *.nmap-file is the required input file for NaviComputer. - -### Creating atlases for nfComPass - -For creating atlases, compatible with [nfComPass](http://www.navifriends.com/phpbbForum/viewtopic.php?f=3&t=17004), you have to click **Atlas -> New Atlas**, select **nfComPass** and give your Atlas a name. -By default atlases with a tilesize of 64x64 are created (recommended). For different tile sizes check **Recreate/adjust map tiles (CPU intensive)** under Layer settings. Set Tileformat can not be changed - it is always png. Maybe you must tryout, what is the best tilesize for your device. Choose your layer and zoomlevels and click **Add selection**. Then click **Create atlas**. Once download and creation has completed, the generated folders can be found in the MOBAC output directory. You must copy the data from the nfComPass.dat to your nfComPass.dat and fill in the path to your mapdirectory. After that, copy the folder(s) to your device. If it is possible, you should not copy the files with Active Sync to your device. - -### Creating OruxMaps atlases - -For creating atlases compatible with [OruxMaps](http://www.oruxmaps.com) as format you have to select **OruxMaps** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). - -Using this atlas output format the following features are ignored when creating atlases: - -* Layer settings, custom tile size. OruxMaps always uses 512x512 tile size. You can select the tile format (PNG or JPEG). If you do not select any, default value is JPEG - quality 90. - -The output format of an "atlas" for OruxMaps is one or more map directories in the atlas directory. You have to copy those maps onto your device (default directory: /oruxmaps/mapfiles/). - -### Creating atlases for OSMAND - -For creating atlases compatible with OSMAND you have to select **OSMAND tile storage** or **OSMAND SQlite** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). -As atlases for OSMAND do not support all features provided by Mobile Atlas Creator the following settings are ignored when creating atlases for OSMAND: - -* Change height or width of the map tiles -* Name of all layers and maps -* Structure of the atlas (which maps belongs to which layer) - -### Creating atlases for Osmdroid - -For creating atlases compatible with Osmdroid you have to select either **Osmdroid ZIP**, **Osmdroid SQLite** or **Osmdroid GEMF** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). -The mentioned three formats are "single file" atlases. One of the other possible atlas formats might also be acceptable for Osmdroid. Also, there is other software that is able to deal with GEMF archives. -As atlases for Osmdroid do not support all features provided by Mobile Atlas Creator the following settings are ignored when creating atlases for Osmdroid: - -* Change height or width of the map tiles -* Name of all layers and maps -* Structure of the atlas (which maps belongs to which layer) - -### Creating atlases for OSMTracker - -For creating atlases compatible with OSMTracker you have to select **OSMTracker tile storage** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). -As atlases for OSMTracker do not support all features provided by Mobile Atlas Creator the following settings are ignored when creating atlases for OSMTracker: - -* Change height or width of the map tiles -* Name of all layers and maps -* Structure of the atlas (which maps belongs to which layer) - -### Creating and using atlases with OziExplorer / large PNG image export - -For creating atlases compatible with OziExplorer you have to select **OziExplorer (PNG & MAP)** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). - -#### Restrictions - -As OziExplorer does not support tiled maps some features are ignored when creating atlases in this format: - -* Image output format is fix: 24bit PNG -* Recreate/adjust map tiles custom tile is ignored - -The output format of an "atlas" for OziExplorer is one subdirectory per layer and within this subdirectory one PNG image and one MAP file per defined map. For opening a map in OziExplorer select the menu **File** → **Load from File** → **Load from MAP file**, browse to the layer directory of the created atlas and select the MAP file. - -If you are only interested in the map image you can safely delete the created map file. - -#### Warning - -Mobile Atlas Creator uses a highly sophisticated and optimized algorithm for creating the PNG files for OziExplorer use. This algorithm allows to create very large maps images at low memory usage. OziExplorer and most image viewers do not use such sophisticated algorithms which can lead to the situation that you can create very large map images - but OziExplorer and other image viewers are not able to open the image. - -### Creating atlases for PathAway - -For creating atlases compatible with PathAway you have to select **PathAway tile cache** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). -As atlases for PathAway do not support all features provided by Mobile Atlas Creator the following restrictions apply when creating atlases for PathAway: - -* The maximum zoom level is 16 - higher zoom levels are not possible with this atlas format -* Tile width and width can not be changed (settings will be ignored) -* Name of all layers and maps is ignored -* Structure of the atlas is ignored (which maps belongs to which layer) - -### Creating and using atlases with RMaps - -For creating offline atlases compatible with [RMaps](http://robertdeveloper.blogspot.com/search/label/rmaps) (Android application) you have to select **RMaps SQLite** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). -The atlas format RMaps does not support all features provided by Mobile Atlas Creator the following settings can not be used or are ignored when creating atlases using this output format: - -* Recreate/adjust map tiles with custom tile size (height and width have to be 256) -* Name of all layers and maps -* Structure of the atlas (which maps belongs to which layer) -* Atlases created after another are merged into one Database named [AtlasName] atlas.sqlitedb which is located in the atlas output directory. - -### [Nokia] Sports Tracker - -For creating atlases compatible with [Sports Tracker(ST)](http://www.sports-tracker.com) you have to select **Sports Tracker** (NOT GPS Sportstracker) as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). - -Do not select **Recreate/adjust map tiles**. - -Maximum Zoomlevel of Sports Tracker is 17, default is 13. - -Copy the created atlas (the whole folder) into the following folder of youre phone (depending of the Sports Tracker version): - -* Sports Tracker 1.76: E:\system\data\Maps\Street\ -* Sports Tracker 2.x: E:\system\data\Maps\Street\ -* Sports Tracker 3.x: E:\system\data\STMaps\Street\ - -For changing the zoom level inside Storts Tracker press 5 to zoom in and 0 to zoom out. - -### Creating and using atlases with Touratech QV / large PNG image export - -For creating atlases compatible with Touratech QV you have to select **Touratech QV** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). - -#### Restrictions - -As Touratech QV does not support tiled maps some features are ignored when creating atlases in this format: - -* Image output format is fix: 24bit PNG -* Recreate/adjust map tiles custom tile is ignored - -The output format of an "atlas" for Touratech QV is one subdirectory per layer and within this subdirectory one PNG image and one CAL file per defined map. - -If you are only interested in the map image you can safely delete the created cal file. - -#### Warning - -Mobile Atlas Creator uses a highly sophisticated and optimized algorithm for creating the PNG files for Touratech QV use. This algorithm allows to create very large maps images at low memory usage. Touratech QV and most image viewers do not use such sophisticated algorithms which can lead to the situation that you can create very large map images - but Touratech QV and other image viewers are not able to open the image. - -### Creating atlases using TomTom Raster format - -TBD - -### Creating and using atlases with TrekBuddy - -For creating atlases compatible with TrekBuddy you have to select **TrekBuddy tared atlas** or **TrekBuddy untared atlas** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). - -After defining the maps and layers for the atlas to be created start atlas download and creation via the button **Create Atlas**. Once atlas download and creation has completed all necessary files belonging to the atlas can be found in the directory atlases\[atlas name]_[current date and time] . - -The atlas itself consists of the atlas startup file cr.tar (tar format) or cr.tba (regular/untared format) and the subdirectories containing the different maps of the atlas. For using the atlas with TrekBuddy copy the whole directory onto your J2ME device. Then use the **Load Atlas** function of TrekBuddy and open cr.tar / cr.tba (in the atlas root directory). - -### Creating and using atlases with TwoNav & CompeGPS Land/Air - -To create atlases compatible with TwoNav software you have to select **TwoNav (RMAP)** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). Atlases created for TwoNav are stored in a format called rmap. It's a binary format that holds the same map data stored at different resolutions - in order to make zooming in and out on low performance mobile devices fast and efficient. However, this causes some restrictions which have to be taken into account: - -* Each map within a layer has to have the same geographical bounds. -* There only can be one map in a layer with a given zoom level - -If there are several layers in one atlas, each layer will be stored as a separate rmap file. - -The easiest way to create a correct atlas content is: first select the appropriate grid zoom (combobox next to the zoom slider), then pick zoom levels from the selected grid zoom up to the zoom level of the desired most detailed level, and finally add a selection to the Atlas content by clicking on the "Add selection" button. - -Rmap format also requires no gaps in a zoom level range from the maximum to the minimum selected zoom level. If there are missing zoom levels, they will be created internally by shrinking the existing downloaded tiles. If the missing zoom levels contain a lot of tiles, this operation could take a while. - -Finally copy the layer.rmap file from the atlases\[atlas name]_[current date and time] folder to your TwoNav maps folder. - -As TwoNav does not support all available features provided my MOBAC, some features can not be used when creating atlases in this format: - -* Custom tile height and width (is ignored for TwoNav RMP atlases) -* Custom tile format: Only JPEG formats are allowed - -### Creating and using atlases with Viewranger - -For creating atlases compatible with [Viewranger(VR)](http://www.viewranger.com/) you have to select **Viewranger** as format in atlas format selection dialog that appears when starting a new atlas (menu **Atlas** entry **New Atlas**). - -Maximum Zoomlevel of Viewranger is 18, minimum is 3. - -After creating youre atlas the folder structure looks like: - -* Mobile Atlas Creator 1.9\atlases\VR_2012-03-28_154944\OSM\13\4308 -* Mobile Atlas Creator 1.9\atlases\VR_2012-03-28_154944\OSM\14\43 -* Mobile Atlas Creator 1.9\atlases\VR_2012-03-28_154944\google\13\4308 -* Mobile Atlas Creator 1.9\atlases\VR_2012-03-28_154944\google\14\43 - -Now we have to [Create a Folder Structure on the Device:](http://support.viewranger.com/wikihelp/index.php/Map_cache_structure) - -If you youre VR Folder is on E: it is on Symbian located in E:/ViewRanger/MapCache/_PAlbTN/ - -In this folder create following Subfolders, if not already present: - -84,85,87,88,89,129 - -e.g. /ViewRanger/MapCache/_PAlbTN/84 - -Copy the content of "OSM" into 84, "google" into 85 and so on. - -Now it looks like: E:/ViewRanger/MapCache/_PAlbTN/13/4308/2687 , 2687 is a tile - -VR has different Online Mapsources which are assigned to the Numbers as shown: - -* OSM->84 -* Opencyclemap->85 -* OSM Direct->87 -* OSM Midnigth->88 -* OSM Fresh->89 -* Open Piste Map->129 - -Of course you can fill the Tilecache with different Maps. - -I use the Open Piste Map eg. as "OSM Public Transport" - -## Enhancement requests - -If you are missing the map provider of your choice or have other enhancement ideas for Mobile Atlas Creator feel free to open an [Feature Request Ticket](http://sourceforge.net/tracker/?group_id=238075&atid=1105497) at SourceForge. - -If have a new online map which is not available in Mobile Atlas Creator there my be change to add it. Before opening a Feature Request please take a look into the [list of map sources known to incompatible with Mobile Atlas Creator](http://svn.code.sf.net/p/mobac/code/tags/MOBAC%201.9/v1.9.16%20final/misc/Incompatible%20maps.txt). - -## Problems, Bugs & Errors - -In case of unexpected errors while executing Mobile Atlas Creator you may get presented a exception dialog containing detailed information about the problem. In such a case please create a new [ticket in the Bug Tracker](http://sourceforge.net/tracker/?group_id=238075&atid=1105494) at SourceForge. Please add the detailed exception information and a detailed description of your last performed actions. - -### The default error log - -By default Mobile Atlas Creator records all errors of the current session into it's error log file Mobile Atlas Creator.log . This log file is located on Windows system in the directory %APPDATA%\Mobile Atlas Creator\ and on Linux/Unix/OSX system in the directory ~/.mobac/ - -### Activate the advanced logging system - -If the recorded errors in the error log do not indicate a problem you can activate the overall message logging mechanism of Mobile Atlas Creator: -Download the file [log4j.xml](http://mobac.sourceforge.net/log4j.xml) and save it in the directory where the jar file of Mobile Atlas Creator is installed to. - -The next start Mobile Atlas Creator will create a log file in the current directory (on Windows this is usually the directory where the JAR file is located on Linux usually the profile directory). Please note that the log file is erased on each program start. If you think you have found a bug please file it in the [bug tracker at SourceForge](http://sourceforge.net/tracker/?group_id=238075&atid=1105494). - -## Known problems and limitations - -### New map sources - -Mobile Atlas Creator is limited to map sources that provide their maps if form of map tiles. Each of that map tiles has to be of size 256x256 pixels. Additionally the map source has to use the spherical Mercator projection and the number of tiles forming the world on each zoom level has to be one of the following values: 20, 21, 22 ... 221, 222. -For more details see OpenStreetMap Wiki: [Slippy map tilenames](http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames), [Mercator](http://wiki.openstreetmap.org/wiki/Mercator), [Height and width of a map](http://wiki.openstreetmap.org/wiki/Height_and_width_of_a_map) and [Zoom levels](http://wiki.openstreetmap.org/wiki/Zoom_levels) - -### Java Bugs - -Due to bugs in Java you should not do the following: - -* Install Mobile Atlas Creator into a directory which path contains an "!" (exclamation mark) because of this [Sun Java bug](http://bugs.sun.com/view_bug.do?bug_id=4523159) -* Do not use OpenJDK if you want to work with GPX tracks in Mobile Atlas Creator -* On Windows without a system proxy set (see connection settings of IE) it is strongly recommended **not to use** the following proxy setting:_Use standard Java proxy settings_ - -## Details for advanced users - -### Specifying directory configuration - -The following steps are necessary if MOBAC is installed to to a directory that is not writable for reguar users: - -For changing the directory configuration pattern for all users of a MOBAC installation save [this file](http://svn.code.sf.net/p/mobac/code/tags/MOBAC%201.9/v1.9.16%20final/directories.ini.template) into the same directory where Mobile_Atlas_Creator.jar has been installed into and change it's name to directories.ini . For more details read the comments in this configuration file. - -### Moving the tile store directory - -Usually the tile store directory where Mobile Atlas Creator saves all downloaded images in is automatically determined. -In case you want to select a different directory perform the following steps: - -1. Make sure you have closed MOBAC -2. Open settings.xml in an text editor -3. Inside of the tag search for the tag . Inside this tag create a new tag named -4. Set the path name to the value of this tag (Windows users should replace backslashes with a slashes) -5. (optional) Copy or move the content of the old tile store directory into the new tile store directory. - -#### Example - -

-    
-        E:/tiles
-    
-    ...
-
- -This specified the windows directory E:\tiles as new tile store directory. The previously used tile store will not be used anymore. -Deleting the tag restores the old behavior (automatically tile store directory selection). - -### Starting external tools from within MOBAC - -External tools like scripts or other executable programs can be started from the **Tools** menu from within MOBAC. This menu is only visible if external programs have been configured. The advantage of starting a program from within MOBAC is that certain information about selected map source, selected region ... can be transmitted as parameters to the executed program. -This allows you for example to create your own maps (render tiles) with external tools like [OSMFILTER](http://wiki.openstreetmap.org/wiki/Osmfilter), [OSMCONVERT](http://wiki.openstreetmap.org/wiki/Osmconvert), [MAPERITIVE](http://maperitive.net/)... - -For defining an external program, create an xml file for each external program to be called. The content of the xml file has to be like one of the following examples. The file-name of the xml is not relevant - it only has to end with .xml - -#### test.xml - -Demonstrates how to execute an Windows batch file. - -

-
- Name shown in tools menu
- cmd.exe /c start .\tools\mybatch.cmd
- MIN_LON MIN_LAT MAX_LON MAX_LAT MIN_ZOOM MAX_ZOOM MAPSOURCE_NAME MAPSOURCE_DISPLAYNAME NAME_EDITBOX 
- true
-
-
- -[Annotated sample file download](http://svn.code.sf.net/p/mobac/code/tags/MOBAC%201.9/v1.9.16%20final/tools/test.xml) - -#### test-exe.xml - -Demonstrates how to execute an regular windows program. - -

-
- Name shown in tools menu
- C:\sample-path\program.exe
- MIN_LON MIN_LAT MAX_LON MAX_LAT MIN_ZOOM MAX_ZOOM MAPSOURCE_NAME MAPSOURCE_DISPLAYNAME NAME_EDITBOX 
- true
-
-
- -The most interesting section is the content of ****. It contains a space separated list of parameters the specified command will be executed with. The following values can be used: - -* MAX_LAT - Maximum latitude (upper border) off the selected area -* MIN_LAT - Minimum latitude (lower border) off the selected area -* MAX_LON - Maximum longitude (right border) off the selected area -* MIN_LON - Minimum longitude (left border) off the selected area -* MIN_ZOOM - minimum zoom of selected zoom levels check-boxes -* MAX_ZOOM - maximum zoom of selected zoom levels check-boxes -* MAPSOURCE_NAME - Currently select map source internal name (used in atlas profile xml file) -* MAPSOURCE_DISPLAYNAME - Currently select map source display name (as shown in the GUI) -* NAME_EDITBOX - content of the edit box "Name" in the side panel "Atlas Content" - -## Custom map sources - -### Simple custom map sources - -Custom map sources which uses a similar URL scheme as Google/OpenStreetMap can be added by saving for each custom map source the definition in form of an xml file in the mapsources directory. - -The following section shows is an example how the xml file has to be formatted. It defines an additional map source named "Custom OSM Mapnik" which shows map tiles identical to the predefined map source "OpenStreetMap Mapnik". - -**Note:**The name specified in there has to be unique among all available map sources within MOBAC. The list of all available map sources can be obtained via command **Show all map source names** in the menu **Debug**. - -

-
-	Custom OSM Mapnik
-	0
-	18
-	png
-	None
-	http://tile.openstreetmap.org/{$z}/{$x}/{$y}.png
-	#000000
-
-
- -The most important part of this definition is the url. It is a template containing specific placeholders which are encapsulated by curly brace: - -* **{$z}** for the zoom level - number range: [_minZoom_ .. _maxZoom_] -* **{$x}** for the x tile coordinate - number range: [0..2_zoom level_ ] -* **{$y}** for the y tile coordinate - number range: [0..2_zoom level_ ] - -Note: If the url contains the ampersand character **&** you have to encode it as **&**. Otherwise it not be valid XML and therefore can not bo loaded by MOBAC. - -Example file for download: [Example custom map source.xml](http://svn.code.sf.net/p/mobac/code/tags/MOBAC%201.9/v1.9.16%20final/mapsources/Example%20custom%20map%20source.xml) - -### Custom WMS map sources - -Similar a WMS map source can be defined. Currently only EPSG:4326 as coordinatesystem is supported. - -

-
-    TerraServer WMS
-    12
-    18
-    JPG
-    1.1.1
-    DRG
-    http://terraserver-usa.com/ogcmap6.ashx?
-    EPSG:4326
-    &EXCEPTIONS=BLANK&Styles=
-    #000000
-
- -Example file (with comments) for download: [Example custom WMS map source.xml](http://svn.code.sf.net/p/mobac/code/tags/MOBAC%201.9/v1.9.16%20final/mapsources/Example%20custom%20WMS%20map%20source.xml) - -### Custom multi-layer map sources - -The same way as [custom map sources](#CustomMapSource) map sources which consist of two or more layers can be defined as well. Note that all except the background map source layer (first in the list) must have transparent parts - otherwise layers in the list before will not be visible. - -

-
-    Custom OSM Mapnik with Hills (Ger)
-    PNG
-    
-        
-            Custom OSM Mapnik
-            0
-            18
-            PNG
-            None
-            http://tile.openstreetmap.org/{$z}/{$x}/{$y}.png
-            #000000
-        
-        
-            Custom transparent hillshade
-            0
-            18
-            PNG
-            None
-            http://www.wanderreitkarte.de/hills/{$z}/{$x}/{$y}.png
-        
-    
-
-
- -Example file for download: [Example custom multi-layer map source.xml](http://svn.code.sf.net/p/mobac/code/tags/MOBAC%201.9/v1.9.16%20final/mapsources/Example%20custom%20multi-layer%20map%20source.xml) - -### Custom CloudMade map sources - -The [CloudMade map service](http://maps.cloudmade.com/) offers a large number of OpenStreetMap based maps with different styles. Each style is accessible through it's styleID . Custom CloudMade maps can be added to MOBAC via a simple XML file containing a map name used by MOBAC and a styleID: - -

-
-    CloudMade blackout
-    1960
-
- -Example file for download: [Example CloudMade1960.xml](http://svn.code.sf.net/p/mobac/code/tags/MOBAC%201.9/v1.9.16%20final/mapsources/Example%20CloudMade1960.xml) - -### Custom BeanShell map sources - -BeanShell map sources as the can be developed using [MapEvaluator](http://sourceforge.net/apps/mediawiki/mobac/index.php?title=MapEvaluator) can be used by MOBAC. To do so place the saved BeanShell code file (file extension .bsh ) in the mapsources directory. It will be loaded on next start-up of MOBAC. - -It is recommended to add a line defining the map source name ([must be unique](#MapSourceNameUnique)). - -
name = "Your map source name here";
- -Example file for download: [Example beanshell map source.bsh](http://svn.code.sf.net/p/mobac/code/tags/MOBAC%201.9/v1.9.16%20final/mapsources/Example%20beanshell%20map%20source.bsh) - -### Custom Map Pack - -Developing a custom map pack requires at least basic Java skills. Therefore the description on how to develop a custom map pack is only part of the source code release of MOBAC. You can get the source code of MOBAC by using the latest src release available in the [files section at Sourceforge](http://sourceforge.net/projects/mobac/files/Mobile%20Atlas%20Creator/) or you can get it directly from the [Subversion code repository](http://sourceforge.net/p/mobac/code/) using the latest trunk version. - -### Custom atlas as map source / locally generated tiles - -Existing atlases or locally rendered tiles can be directly integrated into MOBAC as custom map source without having to set-up a local web-server. -At the moment the formats used by OSMTracker, AndNav, Maverick and OSMAND are supported. For adding such an atlas as map source download the [Example custom tile files source.xml](http://svn.code.sf.net/p/mobac/code/tags/MOBAC%201.9/v1.9.16%20final/mapsources/Example%20custom%20tile%20files%20source.xml) file, adapt the entry and place it in the mapsources directory. - -Tiles can also be packed into one or more zip files and directly used by MOBAC. For details please see the [Example custom tile zip source.xml](http://svn.code.sf.net/p/mobac/code/tags/MOBAC%201.9/v1.9.16%20final/mapsources/Example%20custom%20tile%20zip%20source.xml). -**Note: When working with large ZIP files (more than 4 GB) it is required to use Java 7.** - -SQLite based atlas formats can also be used directly by MOBAC. For details please see the [Example custom tile SQLite source.xml](http://svn.code.sf.net/p/mobac/code/tags/MOBAC%201.9/v1.9.16%20final/mapsources/Example%20custom%20tile%20SQLite%20source.xml) +```shell +bash gradlew dist +``` \ No newline at end of file diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt new file mode 100644 index 0000000..0e4300c --- /dev/null +++ b/ReleaseNotes.txt @@ -0,0 +1,22 @@ +******************************************************************************* +* M O B I L E A T L A S C R E A T O R * +******************************************************************************* +* R E L E A S E N O T E S * +******************************************************************************* + + + Upgrading from version prior to 1.7: + + Starting with MOBAC v1.7 the tile store format has changed. MOBAC now uses a + database (BerkelyDB) based tile store instead of saving each image files + separately in the file system. + + Existing tile stores are NOT CONVERTED into the new database format because + the files in the file system are missing relevant information. Existing old + tile stores are ignored. + + Therefore it is recommended to install MOBAC into a clean directory. + Existing atlas profiles (tac-profile*.xml) created with versions prior to v1.7 + can usually can be reused by copying them into the current directory of MOBAC. + Upon next start of MOBAC they will be automatically renamed and will be + available from the atlas profile selector. \ No newline at end of file diff --git a/TestTileServer.properties b/TestTileServer.properties new file mode 100644 index 0000000..effd706 --- /dev/null +++ b/TestTileServer.properties @@ -0,0 +1,23 @@ +# TCP port on localhost to use +TestHttpServer.port = 80 + +# Allows to simulate not correct working HTTP servers +# Error rate in percent of HTTP 404 responses +TestHttpServer.errorRate = 0 +TestHttpServer.errorOnSpecificUrls = true + +TestHttpServer.delay = 100 + +# Generates for each request a PNG file containing the +# tile data x,y zoom and the tile url +TestHttpServer.generatePNGperRequest = false + +# 0 = MOBAC Logo +# 1 = Gradient blue/white +# 2 = Blue cross +TestHttpServer.staticImage = 2 + +# NO_COMPRESSION = 0 +# BEST_SPEED = 1 +# BEST_COMPRESSION = 9; +TestHttpServer.generatedPNGcompression = 6 \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..b70ccdb --- /dev/null +++ b/build.gradle @@ -0,0 +1,150 @@ +import java.nio.file.Files +import java.nio.file.StandardCopyOption +import java.security.MessageDigest + +plugins { + id 'distribution' + id 'at.bxm.svntools' version '3.1' + id 'org.gradle.crypto.checksum' version '1.4.0' + id 'com.diffplug.spotless' version '6.21.0' +} + +group 'mobac.sourceforge.io' +version '2.3.3' + +println("SVN revision $svntools.info.revisionNumber") + +allprojects { + repositories { + mavenCentral() + maven { + // required for javax.media:jai-core:1.1.3 and com.sun.media:jai-codec:1.1.3 + url "https://repository.jboss.org/maven2" + } + + // maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } + } + ext { + svnRevision = "$svntools.info.revisionNumber" + } + tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' + options.incremental = true + options.fork = true + options.compilerArgs << '-Xlint:unchecked' + options.deprecation = true + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } +} + +task distArchive(type: Zip, dependsOn: ['mobac:createExe', 'mappacks:openstreetmap:jar', "mapevaluator:jar"]) { + + from("mobac/build/libs") { + include "*.jar" + into "/" + } + from("mobac/build/launch4j") { + include "*.exe" + into "/" + } + from(".") { + include "CHANGELOG.txt" + include "ReleaseNotes.txt" + include "gpl.txt" + include "README.html" + include "start.sh" + include "world.map" + into "/" + } + from(project(':mappacks').subprojects.collect { it.tasks.withType(Jar) }) { + into "/mapsources/" + } + from("mapevaluator/build/libs") { + include "MapEvaluator.jar" + into "/" + } + + archiveFileName = "Mobile Atlas Creator ${project.version}.zip" + destinationDirectory = new File(".") +} + +task distSrcArchive(type: Zip) { + + from("/keys") { + include "keystore.txt" + include "*.cer" + into "/keys" + } + from("/mobac") { + exclude "**/build/**" + into "/mobac" + } + from("/mapevaluator") { + exclude "**/build/**" + into "/mapevaluator" + } + from("/mappacks") { + exclude "**/build/**" + into "/mappacks" + } + from("/") { + include "logback.xml" + include "gpl.txt" + include "README.html" + include "README-DEV.html" + include "CHANGELOG.txt" + include "start.sh" + include "world.map" + include "gradle/**" + include "gradle*" + include "settings.gradle" + include "gradle*" + include "build.gradle" + } + archiveFileName = "Mobile Atlas Creator ${project.version} src.zip" + destinationDirectory = new File(".") +} +task dist { + dependsOn(distArchive, distSrcArchive) +} + +/** + * Generate MD5 file for map packs online update. This task is irreelvant for regular MOBAC users/developers + */ +task mappacksMd5 { + var mapPackDir = "${project.projectDir}/mappacks" + var writer = new StringWriter() + var updDir = project.file('mapsources-updates').toPath() + delete updDir + Files.createDirectories(updDir) + fileTree("$mapPackDir").matching { + include "**/build/libs/mp-*.jar" + }.each { + // do some operations + var p = it.toPath() + var dest = updDir.resolve(it.getName()) + Files.copy(p, dest, StandardCopyOption.REPLACE_EXISTING) + println(dest) + + var bytes = Files.readAllBytes(dest) + var md5 = MessageDigest.getInstance("MD5").digest(bytes).encodeHex().toString() + writer.append(String.format("%s %s\n", md5, it.name)) + } + println(writer.toString()) + Files.writeString(updDir.resolve("mappacks-md5.txt"), writer.toString()) +} + +spotless { + java { + target fileTree(rootDir).matching { + include '**/*.java' + } + removeUnusedImports() + eclipse() + lineEndings(com.diffplug.spotless.LineEnding.WINDOWS) + encoding("UTF-8") + trimTrailingWhitespace() + endWithNewline() + } +} diff --git a/build.xml b/build.xml deleted file mode 100644 index c9fd4f6..0000000 --- a/build.xml +++ /dev/null @@ -1,376 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -libraryjars "${rtlibraryjar}" - -injars - "${jar.name}" - -outjars - build/temp.jar - -keepattributes *Annotation* - -keep class ${main.class} { - public static void main(java.lang.String[]); } - -keep class - mobac.program.* { public *; } - -keep class mobac.program.interfaces.* { - public *; } - -keep class mobac.program.model.package-info - -keep class - mobac.program.model.* { public *; } - -keep class mobac.program.jaxb.* { - public *; } - -keep class mobac.program.interfaces.* { public *; } - -keep - class mobac.program.download.UserAgent { public *; } - -keep class - mobac.exceptions.* { public *; } - -keep class - mobac.program.tilestore.berkeleydb.* { *; } - -keep class - mobac.program.tilestore.TileStoreEntry { public *; } - -keep class - mobac.program.atlascreators.AtlasCreator { public *; } - -keep class - mobac.utilities.beanshell.* { public *; } - -keep class - mobac.utilities.tar.TarIndex { public *; } - -keep class - mobac.utilities.tar.TarIndexedArchive { public *; } - -keep class - mobac.data.gpx.gpx11.* { public *; } - -keep class - mobac.mapsources.MapSourceTools { public *; } - -keep class - mobac.mapsources.MapSourceUrlUpdater { public *; } - -keep class - mobac.mapsources.custom.* { *; } - -keep class org.apache.log4j.Layout { - public *; } - -keep class org.apache.log4j.Level { public *; } - -keep - class org.apache.commons.lang3.StringEscapeUtils { public *; } - -keep - class org.apache.log4j.Category { public *; } - -keep class - org.apache.log4j.Priority { public *; } - -keep class - org.apache.log4j.spi.LoggingEvent { public *; } - -keep class - org.apache.log4j.spi.ThrowableInformation { public *; } - -keep class - org.apache.log4j.spi.LocationInfo { public *; } - -keep class - org.apache.log4j.PatternLayout { public *; } - -keep class - org.apache.log4j.Appender { public *; } - -keep class - org.apache.log4j.FileAppender { public *; } - -keep class - com.sixlegs.png.PngImage { public *; } - -keep class bsh.This { public - *; } - -keep class bsh.XThis { public *; } - -keep class - com.sleepycat.persist.PrimaryIndex { public *; } - -keepclassmembers - enum * { - public static **[] values(); - public static ** - valueOf(java.lang.String); - } - -keepclassmembers class * - implements - java.io.Serializable { - static final long serialVersionUID; - private void - writeObject(java.io.ObjectOutputStream); - private void - readObject(java.io.ObjectInputStream); - java.lang.Object - writeReplace(); - java.lang.Object readResolve(); - } - -keepclassmembers - class * implements - com.sleepycat.persist.evolve.Conversion { - boolean - equals(java.lang.Object); - } - -dontnote java.** - -dontnote javax.** - -dontnote com.sun.** - -dontnote sun.** - -dontwarn - -dontoptimize - -dontobfuscate - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/directories.ini.Linux-XDG Base-Directory-Specification b/directories.ini.Linux-XDG Base-Directory-Specification new file mode 100644 index 0000000..b9bcdc4 --- /dev/null +++ b/directories.ini.Linux-XDG Base-Directory-Specification @@ -0,0 +1,36 @@ +####################################################################### +# MOBAC system wide directory configuration # +# for a Linux/Unix distribution compliant with # +# XDG Base Directory Specification v0.7 # +# http://standards.freedesktop.org/basedir-spec/basedir-spec-0.7.html # +####################################################################### +# # +# Required environment variables: # +# $XDG_CONFIG_HOME - usually $HOME/.config # +# $XDG_CACHE_HOME - usually $HOME/.cache # +# # +####################################################################### +# # +# Rename this file to "directories.ini" and place it in the same # +# directory as the file Mobile-Atlas_Creator.jar # +# # +####################################################################### + +# Directory where to save settings.xml and search for log4j.xml +mobac.usersettingsdir=${XDG_CONFIG_HOME}/mobac + +# Directory where to save and load atlas profiles +mobac.atlasprofilesdir=${XDG_CONFIG_HOME}/mobac + +# Directory where to search "map packs", custom maps and beanShell map sources +# Updated map packs are also saved into this directory overwriting old ones +mobac.mapsourcesdir=${XDG_CONFIG_HOME}/mobac/mapsources + +# Directory where to create the cache databases of downloaded tiles +mobac.tilestoredir=${XDG_CACHE_HOME}/mobac/tilestore + +# Directory where to save config files for executing external tools from within MOBAC +mobac.toolsdir=${XDG_CACHE_HOME}/mobac/tools + +# Directory where to create the temporary download container +# mobac.tmpdir=${TMP}/mobac \ No newline at end of file diff --git a/directories.ini.template b/directories.ini.template new file mode 100644 index 0000000..f077a97 --- /dev/null +++ b/directories.ini.template @@ -0,0 +1,45 @@ +################################################ +# MOBAC system wide directory configuration +################################################ +# +# For activating this configuration file rename it to "directories.ini" +# (remove the .template extension) and place it in the same directory as +# the file Mobile_Atlas_Creator.jar +# +# You can use any available system variable - but you have to write it in Java notation +# +# Therefore the tmp directory is available on all platforms via "${TMP}" +# +# Besides the default system variables MOBAC defines two own variables: +# +# ${home} +# user home directory, e.g. /home/username/ on Linux or C:\Users\username\ on Win Vista/7 +# +# ${mobac-prog} +# directory where MOBAC (or to be detailed Mobile_Atlas_Creator.jar) has been installed into +# +# Notes: +# On Windows you have to use slashes "/" instead of back-slashes "\" e.g. C:/temp/mobac +# Absolute pathes are also valid + +#Uncomment one of the following lines starting with "mobac." for redefining the directory + +# Directory where to save settings.xml and search for log4j.xml +#mobac.usersettingsdir=${home}/.mobac +mobac.usersettingsdir=D:/MOBAC + +# Directory where to save and load atlas profiles +#mobac.atlasprofilesdir=${home}/.mobac + +# Directory where to search "map packs", custom maps and beanShell map sources +# Updated map packs are also saved into this directory overwriting old ones +#mobac.mapsourcesdir=${mobac-prog}/mapsources + +# Directory where to create the cache databases of downloaded tiles +mobac.tilestoredir=D:/MOBAC/tilestore + +# Directory where to save config files for executing external tools from within MOBAC +#mobac.toolsdir=${mobac-prog}/tools + +# Directory where to create the temporary download container +mobac.tmpdir=D:/MOBAC/Temp \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..5178000 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.parallel=true +org.gradle.warning.mode=all diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..7f93135 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..2ea3535 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..0adc8e1 --- /dev/null +++ b/gradlew @@ -0,0 +1,249 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..6689b85 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/keys/MapPack.cer b/keys/MapPack.cer new file mode 100644 index 0000000..f2dc964 Binary files /dev/null and b/keys/MapPack.cer differ diff --git a/keys/keystore.txt b/keys/keystore.txt new file mode 100644 index 0000000..bdc3230 --- /dev/null +++ b/keys/keystore.txt @@ -0,0 +1,2 @@ +keytool -genkey -keyalg RSA -alias MapPack -validity 7300 -dname "CN=MOBAC MapPack Signer 2015" -keystore keystore.jks +keytool -exportcert -keystore keystore.jks -alias MapPack -file MapPack.cer diff --git a/lib/Tidy.jar b/lib/Tidy.jar deleted file mode 100644 index a98a60f..0000000 Binary files a/lib/Tidy.jar and /dev/null differ diff --git a/lib/ant-contrib-for.jar b/lib/ant-contrib-for.jar deleted file mode 100644 index 69e8998..0000000 Binary files a/lib/ant-contrib-for.jar and /dev/null differ diff --git a/lib/bsh-2.0b4.jar b/lib/bsh-2.0b4.jar deleted file mode 100644 index 36fe03d..0000000 Binary files a/lib/bsh-2.0b4.jar and /dev/null differ diff --git a/lib/commons-codec-1.4.jar b/lib/commons-codec-1.4.jar deleted file mode 100644 index 458d432..0000000 Binary files a/lib/commons-codec-1.4.jar and /dev/null differ diff --git a/lib/commons-io-2.0.jar b/lib/commons-io-2.0.jar deleted file mode 100644 index d5fa741..0000000 Binary files a/lib/commons-io-2.0.jar and /dev/null differ diff --git a/lib/commons-lang3-3.1.jar b/lib/commons-lang3-3.1.jar deleted file mode 100644 index a85e539..0000000 Binary files a/lib/commons-lang3-3.1.jar and /dev/null differ diff --git a/lib/itextpdf-5.1.0.jar b/lib/itextpdf-5.1.0.jar deleted file mode 100644 index e84ae38..0000000 Binary files a/lib/itextpdf-5.1.0.jar and /dev/null differ diff --git a/lib/jai_codec.jar b/lib/jai_codec.jar deleted file mode 100644 index 056ecd3..0000000 Binary files a/lib/jai_codec.jar and /dev/null differ diff --git a/lib/jai_core.jar b/lib/jai_core.jar deleted file mode 100644 index b29b8ee..0000000 Binary files a/lib/jai_core.jar and /dev/null differ diff --git a/lib/javapng-2.0.jar b/lib/javapng-2.0.jar deleted file mode 100644 index 8c01f8d..0000000 Binary files a/lib/javapng-2.0.jar and /dev/null differ diff --git a/lib/je-3.3.93.jar b/lib/je-3.3.93.jar deleted file mode 100644 index 9a9ff07..0000000 Binary files a/lib/je-3.3.93.jar and /dev/null differ diff --git a/lib/log4j-1.2.15.jar b/lib/log4j-1.2.15.jar deleted file mode 100644 index c930a6a..0000000 Binary files a/lib/log4j-1.2.15.jar and /dev/null differ diff --git a/lib/proguard-ant-7.0.0.jar b/lib/proguard-ant-7.0.0.jar deleted file mode 100644 index ee025f8..0000000 Binary files a/lib/proguard-ant-7.0.0.jar and /dev/null differ diff --git a/lib/proguard-base-7.0.0.jar b/lib/proguard-base-7.0.0.jar deleted file mode 100644 index d073451..0000000 Binary files a/lib/proguard-base-7.0.0.jar and /dev/null differ diff --git a/lib/proguard-core-7.0.0.jar b/lib/proguard-core-7.0.0.jar deleted file mode 100644 index fe8883f..0000000 Binary files a/lib/proguard-core-7.0.0.jar and /dev/null differ diff --git a/lib/proguard.jar b/lib/proguard.jar deleted file mode 100644 index 21d93ce..0000000 Binary files a/lib/proguard.jar and /dev/null differ diff --git a/lib/servlet.jar b/lib/servlet.jar deleted file mode 100644 index 9cccc09..0000000 Binary files a/lib/servlet.jar and /dev/null differ diff --git a/lib/simmetrics_jar_v1_6_2_d07_02_07.jar b/lib/simmetrics_jar_v1_6_2_d07_02_07.jar deleted file mode 100644 index 17bf711..0000000 Binary files a/lib/simmetrics_jar_v1_6_2_d07_02_07.jar and /dev/null differ diff --git a/lib/sqlite-jdbc-3.7.15-M1.jar b/lib/sqlite-jdbc-3.7.15-M1.jar deleted file mode 100644 index 97b306f..0000000 Binary files a/lib/sqlite-jdbc-3.7.15-M1.jar and /dev/null differ diff --git a/lib/webserver.jar b/lib/webserver.jar deleted file mode 100644 index 36957e5..0000000 Binary files a/lib/webserver.jar and /dev/null differ diff --git a/mapevaluator/build.gradle b/mapevaluator/build.gradle new file mode 100644 index 0000000..c3e7d51 --- /dev/null +++ b/mapevaluator/build.gradle @@ -0,0 +1,22 @@ +plugins { + id 'java' +} + +dependencies { + implementation project(':mobac') + implementation project(':mappacks:openstreetmap') + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.0' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' +} + +test { + useJUnitPlatform() +} +jar{ + archiveFileName = "MapEvaluator.jar" + manifest { + attributes "Main-Class": "mobac.StartMapEvaluator" + attributes "Class-Path": "Mobile_Atlas_Creator.jar" + attributes 'Add-Exports': 'java.base/sun.net.www.protocol.http java.base/sun.net.www.protocol.https' + } +} \ No newline at end of file diff --git a/mapevaluator/src/main/java/mobac/StartMapEvaluator.java b/mapevaluator/src/main/java/mobac/StartMapEvaluator.java new file mode 100644 index 0000000..2d36562 --- /dev/null +++ b/mapevaluator/src/main/java/mobac/StartMapEvaluator.java @@ -0,0 +1,35 @@ +package mobac; + +import mobac.gui.MapEvaluator; +import mobac.mapsources.DefaultMapSourcesManager; +import mobac.program.DirectoryManager; +import mobac.program.ProgramInfo; +import mobac.program.model.Settings; +import mobac.program.tilestore.TileStore; +import mobac.utilities.GUIExceptionHandler; + +public class StartMapEvaluator { + + public static void main(String[] args) { + StartMOBAC.setLookAndFeel(); + ProgramInfo.PROG_NAME = "MOBAC Map Evaluator"; + ProgramInfo.PROG_NAME_SHORT = null; + GUIExceptionHandler.registerForCurrentThread(); + GUIExceptionHandler.installToolkitEventQueueProxy(); + ProgramInfo.initialize(); + // Logging.configureConsoleLogging(Level.TRACE, Logging.ADVANCED_LAYOUT); + DirectoryManager.initialize(); + // MapEvaluatorMapSourcesManager.initialitze(); + DefaultMapSourcesManager.initialize(); + try { + if (Settings.FILE.isFile()) { + Settings.load(); + } + } catch (Exception e) { + // Load settings.xml only if it exists + } + TileStore.initialize(); + new MapEvaluator().setVisible(true); + } + +} diff --git a/mapevaluator/src/main/java/mobac/gui/MapEvaluator.java b/mapevaluator/src/main/java/mobac/gui/MapEvaluator.java new file mode 100644 index 0000000..3a40bde --- /dev/null +++ b/mapevaluator/src/main/java/mobac/gui/MapEvaluator.java @@ -0,0 +1,327 @@ +package mobac.gui; + +import bsh.EvalError; +import mobac.gui.actions.HelpAction; +import mobac.gui.components.LineNumberedPaper; +import mobac.gui.mapview.LogPreviewMap; +import mobac.mapsources.MapEvaluatorBeanShellHttpMapSource; +import mobac.mapsources.MapSourcesManager; +import mobac.mapsources.custom.BeanShellHttpMapSource; +import mobac.mapsources.loader.CustomMapSourceLoader; +import mobac.program.DirectoryManager; +import mobac.program.ProgramInfo; +import mobac.program.interfaces.HttpMapSource; +import mobac.program.interfaces.MapSource; +import mobac.program.model.EastNorthCoordinate; +import mobac.tools.MapSourceCapabilityDetector; +import mobac.tools.MapSourceCapabilityGUI; +import mobac.utilities.GUIExceptionHandler; +import mobac.utilities.Utilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JToolBar; +import javax.swing.filechooser.FileNameExtensionFilter; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.HeadlessException; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStreamWriter; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; + +public class MapEvaluator extends JFrame { + + private static MapEvaluator INSTANCE; + private final LogPreviewMap previewMap; + private final JSplitPane splitPane; + private final LineNumberedPaper mapSourceEditor; + private final CustomMapSourceLoader xmlLoader; + private final MapSource defaultOsmMapSource; + protected final Logger log; + private File chooserDir; + + private File loadedFile; + + public MapEvaluator() throws HeadlessException { + super(ProgramInfo.getCompleteTitle()); + log = LoggerFactory.getLogger(this.getClass()); + addWindowListener(new MEWindowAdapter()); + setMinimumSize(new Dimension(300, 300)); + setLayout(new BorderLayout()); + setDefaultCloseOperation(EXIT_ON_CLOSE); + previewMap = new LogPreviewMap(); + + // previewMap.setMapMarkerVisible(true); + // previewMap.addMapMarker(new ReferenceMapMarker(Color.RED, 1, 2)); + + defaultOsmMapSource = MapSourcesManager.getInstance().getDefaultMapSource(); + + chooserDir = DirectoryManager.mapSourcesDir; + + xmlLoader = new CustomMapSourceLoader(null, null); + mapSourceEditor = new LineNumberedPaper(3, 60); + try { + String code = Utilities.loadTextResource("bsh/default.bsh"); + mapSourceEditor.setText(code); + } catch (IOException e) { + log.error("", e); + } + JPanel bottomPanel = new JPanel(new BorderLayout()); + JToolBar toolBar = new JToolBar("Toolbar"); + addButtons(toolBar); + bottomPanel.setMinimumSize(new Dimension(200, 100)); + + JScrollPane editorScrollPane = new JScrollPane(mapSourceEditor); + bottomPanel.add(toolBar, BorderLayout.NORTH); + bottomPanel.add(editorScrollPane, BorderLayout.CENTER); + splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, previewMap, bottomPanel); + add(splitPane, BorderLayout.CENTER); + setSize(800, 600); + setExtendedState(JFrame.MAXIMIZED_BOTH); + INSTANCE = this; + } + + public static void log(String msg) { + INSTANCE.previewMap.addLog(msg); + } + + private void addButtons(JToolBar toolBar) { + JButton button = null; + + button = new JButton("Load Template", Utilities.loadResourceImageIcon("new-icon.png")); + button.setToolTipText("Reset custom code editor to one of several templates"); + button.addActionListener((event) -> loadTemplate()); + toolBar.add(button); + + button = new JButton("Load", Utilities.loadResourceImageIcon("open-icon.png")); + button.setToolTipText("Load custom map source from file"); + button.addActionListener((event) -> loadMapSource()); + toolBar.add(button); + + button = new JButton("Save", Utilities.loadResourceImageIcon("save-icon.png")); + button.setToolTipText("Save custom map source to file"); + button.addActionListener((event) -> saveMapSource()); + toolBar.add(button); + + button = new JButton("Execute code", Utilities.loadResourceImageIcon("check-icon.png")); + button.setToolTipText("Switch to custom map source (as defined by the custom code)"); + button.addActionListener((event) -> executeCode()); + toolBar.add(button); + + button = new JButton("OSM", Utilities.loadResourceImageIcon("osm-icon.png")); + button.setToolTipText("Switch back to predefined OpenStreetMap mapsource"); + button.addActionListener((event) -> previewMap.setMapSource(defaultOsmMapSource)); + toolBar.add(button); + button = new JButton("Toggle tile info", Utilities.loadResourceImageIcon("info-icon.png")); + button.setToolTipText("Show/hide tile info"); + button.addActionListener((event) -> previewMap.setTileGridVisible(!previewMap.isTileGridVisible())); + toolBar.add(button); + + button = new JButton("Test Capabilities", Utilities.loadResourceImageIcon("capabilities-icon.png")); + button.setToolTipText("Test the tile-update capabilities for the current map
" + + "using the current center of the map as test point"); + button.addActionListener((event) -> testCapabilities()); + toolBar.add(button); + + // button = new JButton("Log"); + // button.setToolTipText("Show Log"); + // button.addActionListener((event) -> showLog()); + // toolBar.add(button); + + button = new JButton("Help", Utilities.loadResourceImageIcon("help-icon.png")); + button.setToolTipText("Show help dialog"); + button.addActionListener(new HelpAction()); + toolBar.add(button); + } + + private void showLog() { + + } + private void loadTemplate() { + try { + String[] options = {"Empty", "OpenStreetMap Mapnik"}; + int a = JOptionPane.showOptionDialog(MapEvaluator.this, "Please select an template", "Select template", 0, + JOptionPane.QUESTION_MESSAGE, null, options, options[0]); + String code = ""; + switch (a) { + case (0) : + code = Utilities.loadTextResource("bsh/empty.bsh"); + break; + case (1) : + code = Utilities.loadTextResource("bsh/osm.bsh"); + break; + } + + mapSourceEditor.setText(code); + } catch (IOException e) { + log.error("", e); + } + } + + private void loadMapSource() { + try { + final JFileChooser fc = getMapSourceFileChooser(false); + int returnVal = fc.showOpenDialog(MapEvaluator.this); + if (returnVal != JFileChooser.APPROVE_OPTION) { + return; + } + chooserDir = fc.getSelectedFile().getParentFile(); + List lines = Files.readAllLines(fc.getSelectedFile().toPath(), StandardCharsets.UTF_8); + StringWriter sw = new StringWriter(); + for (String s : lines) { + sw.write(s); + sw.write("\n"); + } + mapSourceEditor.setText(sw.toString()); + loadedFile = fc.getSelectedFile(); + } catch (IOException e) { + log.error("", e); + JOptionPane.showMessageDialog(MapEvaluator.this, "Error reading code from file:\n" + e.getMessage(), + "Loading failed", JOptionPane.ERROR_MESSAGE); + } + } + + private void saveMapSource() { + final JFileChooser fc = getMapSourceFileChooser(true); + int returnVal = fc.showOpenDialog(MapEvaluator.this); + if (returnVal != JFileChooser.APPROVE_OPTION) { + return; + } + chooserDir = fc.getSelectedFile().getParentFile(); + try (BufferedWriter bw = new BufferedWriter( + new OutputStreamWriter(new FileOutputStream(fc.getSelectedFile()), StandardCharsets.UTF_8))) { + bw.write(mapSourceEditor.getText()); + } catch (IOException e) { + log.error("", e); + JOptionPane.showMessageDialog(MapEvaluator.this, "Error writing code to disk:\n" + e.getMessage(), + "Saving failed", JOptionPane.ERROR_MESSAGE); + } + } + + private JFileChooser getMapSourceFileChooser(boolean save) { + final JFileChooser fc = new JFileChooser(); + if (save) { + fc.setDialogTitle("Save custom map source"); + fc.setDialogType(JFileChooser.SAVE_DIALOG); + fc.setSelectedFile(loadedFile); + } else { + fc.setDialogTitle("Load custom map source"); + fc.setDialogType(JFileChooser.OPEN_DIALOG); + } + fc.setCurrentDirectory(chooserDir); + fc.setFileSelectionMode(JFileChooser.FILES_ONLY); + FileNameExtensionFilter defaultFilter = new FileNameExtensionFilter("MOBAC custom map source", "bsh", "xml"); + fc.addChoosableFileFilter(defaultFilter); + fc.addChoosableFileFilter(new FileNameExtensionFilter("Beanshell map source", "bsh")); + fc.addChoosableFileFilter(new FileNameExtensionFilter("Custom XML map source", "xml")); + fc.setFileFilter(defaultFilter); + return fc; + } + + private void testCapabilities() { + final MapSource mapSource = previewMap.getMapSource(); + final EastNorthCoordinate coordinate = previewMap.getCenterCoordinate(); + + final List result = new ArrayList<>(); + Runnable r = () -> { + + MapSourceCapabilityGUI gui = null; + try { + gui = new MapSourceCapabilityGUI(result); + gui.setWorkerThread(Thread.currentThread()); + gui.setVisible(true); + for (int zoom = mapSource.getMinZoom(); zoom < mapSource.getMaxZoom(); zoom++) { + MapSourceCapabilityDetector mstd = new MapSourceCapabilityDetector((HttpMapSource) mapSource, + coordinate, zoom); + if (!gui.isVisible()) { + return; + } + mstd.testMapSource(); + result.add(mstd); + gui.refresh(); + Utilities.checkForInterruption(); + } + gui.toFront(); + } catch (InterruptedException e) { + } finally { + gui.workerFinished(); + } + }; + new Thread(r).start(); + } + + private void executeCode() { + String code = mapSourceEditor.getText().trim(); + if (code.startsWith(""); + sw.append("

Available tools function:

"); + + Method[] methods = Tools.class.getMethods(); + + ParamReader pr = null; + try { + pr = new ParamReader(Tools.class); + } catch (IOException e1) { + e1.printStackTrace(); + } + for (Method m : methods) { + if (!Tools.class.equals(m.getDeclaringClass())) { + continue; + } + // sw.append("

" + m.getName() + "

"); + sw.append("
"); + sw.append("
");
+			sw.append(getClassName(m.getReturnType()) + " Tools." + m.getName() + "(");
+			Class[] params = m.getParameterTypes();
+			String[] names = pr.getParameterNames(m);
+			int last = params.length - 1;
+			for (int i = 0; i < params.length; i++) {
+				sw.append(getClassName(params[i]));
+				if (names != null) {
+					sw.append(" " + names[i]);
+				}
+				if (i != last) {
+					sw.append(", ");
+				}
+			}
+			sw.append(")
"); + MethodDescription md = m.getAnnotation(Tools.MethodDescription.class); + if (md != null) { + sw.append(md.value() + "
"); + } + } + + sw.append("
"); + sw.append(""); + JOptionPane.showMessageDialog(null, sw.toString(), "Help", JOptionPane.PLAIN_MESSAGE); + } + + private String getClassName(Class clazz) { + if (clazz.isArray()) { + String name = clazz.getName(); + switch (name.charAt(1)) { + case 'B' : + return "byte[]"; + case 'C' : + return "char[]"; + case 'D' : + return "double[]"; + case 'F' : + return "float[]"; + case 'I' : + return "int[]"; + case 'J' : + return "long[]"; + case 'L' : + return "Object"; + case 'S' : + return "short[]"; + case 'Z' : + return "boolean[]"; + default : + return "unknown[]"; + } + } else { + return clazz.getSimpleName(); + } + } +} diff --git a/mapevaluator/src/main/java/mobac/gui/components/LineNumberedBorder.java b/mapevaluator/src/main/java/mobac/gui/components/LineNumberedBorder.java new file mode 100644 index 0000000..7fac885 --- /dev/null +++ b/mapevaluator/src/main/java/mobac/gui/components/LineNumberedBorder.java @@ -0,0 +1,252 @@ +package mobac.gui.components; + +import javax.swing.JTextArea; +import javax.swing.border.AbstractBorder; +import java.awt.Component; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; + +/** + * Draws line numbers next to each line, in the same font as the text. + * Currently, this can only be used with a JTextArea , since it relies + * on the getRows() and getLineCount() methods. A possible + * extension, create an interface to return this rows/linecount. + * + * @created January 29, 2002 + * @see http://www.esus.com/docs/GetQuestionPage.jsp?uid=1326 + */ +public class LineNumberedBorder extends AbstractBorder { + + /** + * The line numbers should be drawn on the left side of the component. + */ + public static int LEFT_SIDE = -2; + + /** + * The line numbers should be drawn on the right side of the component. + */ + public static int RIGHT_SIDE = -1; + + /** + * The line number should be right justified. + */ + public static int RIGHT_JUSTIFY = 0; + + /** + * The line number should be left justified. + */ + public static int LEFT_JUSTIFY = 1; + + /** + * Indicates the justification of the text of the line number. + */ + private int lineNumberJustification = RIGHT_JUSTIFY; + + /** + * Indicates the location of the line numbers, w.r.t. the component. + */ + private int location = LEFT_SIDE; + + public LineNumberedBorder(int location, int justify) { + setLocation(location); + setLineNumberJustification(justify); + } + + public Insets getBorderInsets(Component c) { + return getBorderInsets(c, new Insets(0, 0, 0, 0)); + } + + /** + * Create the string for the line number. NOTE: The length param does + * not include the optional space added after the line number. + * + * @param lineNumber + * to stringize + * @param length + * the length desired of the string + * @param addSpace + * Description of the Parameter + * @return the line number for drawing + */ + private static String padLabel(int lineNumber, int length, boolean addSpace) { + StringBuffer buffer = new StringBuffer(); + buffer.append(lineNumber); + for (int count = (length - buffer.length()); count > 0; count--) { + buffer.insert(0, ' '); + } + if (addSpace) { + buffer.append(' '); + } + return buffer.toString(); + } + + public int getLineNumberJustification() { + return lineNumberJustification; + } + + public void setLineNumberJustification(int justify) { + if (justify == RIGHT_JUSTIFY || justify == LEFT_JUSTIFY) { + lineNumberJustification = justify; + } + } + + public int getLocation() { + return location; + } + + public void setLocation(int loc) { + if (loc == RIGHT_SIDE || loc == LEFT_SIDE) { + location = loc; + } + } + + /** + * This modifies the insets, by adding space for the line number on the left. + * Should be modified to add space on the right, depending upon Locale. + * + * @param c + * Description of the Parameter + * @param insets + * Description of the Parameter + * @return The borderInsets value + */ + public Insets getBorderInsets(Component c, Insets insets) { + // if c is not a JTextArea...nothing is done... + if (c instanceof JTextArea) { + int width = lineNumberWidth((JTextArea) c); + if (location == LEFT_SIDE) { + insets.left = width; + } else { + insets.right = width; + } + } + return insets; + } + + // + // NOTE: This method is called every time the cursor blinks... + // so...optimize (later and if possible) for speed... + // + public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { + + java.awt.Rectangle clip = g.getClipBounds(); + + FontMetrics fm = g.getFontMetrics(); + int fontHeight = fm.getHeight(); + + // starting location at the "top" of the page... + // y is the starting baseline for the font... + // should "font leading" be applied? + int ybaseline = y + fm.getAscent(); + + // + // now determine if it is the "top" of the page...or somewhere else + // + int startingLineNumber = (clip.y / fontHeight) + 1; + + // + // use any one of the following if's: + // + // if (startingLineNumber != 1) + if (ybaseline < clip.y) { + // + // not within the clip rectangle...move it... + // determine how many fontHeight's there are between + // y and clip.y...then add that many fontHeights + // + ybaseline = y + startingLineNumber * fontHeight - (fontHeight - fm.getAscent()); + } + + // + // options: + // . write the number rows in the document (current) + // . write the number of existing lines in the document (to do) + // see getLineCount() + // + + // determine which the "drawing" should end... + // add fontHeight: make sure...part of the line number is drawn + // + // could also do this by determining what the last line + // number to draw. + // then the "while" loop whould change accordingly. + // + // int yend = y + clip.height + fontHeight; + // int yend = ybaseline + height + fontHeight; // original + int yend = ybaseline + height; + if (yend > (y + height)) { + yend = y + height; + } + + JTextArea jta = (JTextArea) c; + int lineWidth = lineNumberWidth(jta); + + // base x position of the line number + int lnxstart = x; + if (location == LEFT_SIDE) { + // x (LEFT) or (x + lineWidth) (RIGHT) + // (depends upon justification) + if (lineNumberJustification == LEFT_JUSTIFY) { + lnxstart = x; + } else { + // RIGHT JUSTIFY + lnxstart = x + lineWidth; + } + } else { + // RIGHT SIDE + // (y + width) - lineWidth (LEFT) or (y + width) (RIGHT) + // (depends upon justification) + if (lineNumberJustification == LEFT_JUSTIFY) { + lnxstart = (y + width) - lineWidth; + } else { + // RIGHT JUSTIFY + lnxstart = (y + width); + } + } + + g.setColor(c.getForeground()); + // + // loop until out of the "visible" region... + // + int length = ("" + Math.max(jta.getRows(), jta.getLineCount() + 1)).length(); + while (ybaseline < yend) { + // + // options: + // . left justify the line numbers + // . right justify the line numbers + // + + if (lineNumberJustification == LEFT_JUSTIFY) { + g.drawString(startingLineNumber + " ", lnxstart, ybaseline); + } else { + // right justify + String label = padLabel(startingLineNumber, length, true); + g.drawString(label, lnxstart - fm.stringWidth(label), ybaseline); + } + + ybaseline += fontHeight; + startingLineNumber++; + } + } + + // paintComponent + + /** + * Returns the width, in pixels, of the maximum line number, plus a trailing + * space. + * + * @param textArea + * Description of the Parameter + * @return Description of the Return Value + */ + private int lineNumberWidth(JTextArea textArea) { + // + // note: should this be changed to use all nines for the lineCount? + // for example, if the number of rows is 111...999 could be wider + // (in pixels) in a proportionally spaced font... + // + int lineCount = Math.max(textArea.getRows(), textArea.getLineCount() + 1); + return textArea.getFontMetrics(textArea.getFont()).stringWidth(lineCount + " "); + } +} diff --git a/mapevaluator/src/main/java/mobac/gui/components/LineNumberedPaper.java b/mapevaluator/src/main/java/mobac/gui/components/LineNumberedPaper.java new file mode 100644 index 0000000..25d56f4 --- /dev/null +++ b/mapevaluator/src/main/java/mobac/gui/components/LineNumberedPaper.java @@ -0,0 +1,198 @@ +package mobac.gui.components; + +import javax.swing.JTextArea; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; + +/** + * Draws line numbers next to each line, in the same font as the text. Based + * upon the comment in {@link #getInsets(Insets) getInsets} maybe the "line + * numbering" could be a border? + * + * @see http://www.esus.com/docs/GetQuestionPage.jsp?uid=1326 + */ +public class LineNumberedPaper extends JTextArea { + + /** + * The line number should be right justified. + */ + public static int RIGHT_JUSTIFY = 0; + + /** + * The line number should be left justified. + */ + public static int LEFT_JUSTIFY = 1; + + /** + * Indicates the justification of the text of the line number. + */ + private int lineNumberJustification = RIGHT_JUSTIFY; + + public LineNumberedPaper(int rows, int cols) { + super(rows, cols); + setOpaque(false); + // if this is NOT opaque...then painting is a problem... + // basically...this draws the line numbers... + // but...super.paintComponent()...erases the background...and the + // line numbers...what to do? + // + // "workaround": paint the background in this class... + } + + public Insets getInsets() { + return getInsets(new Insets(0, 0, 0, 0)); + } + + /** + * This modifies the insets, by adding space for the line number on the left. + * Should be modified to add space on the right, depending upon Locale. + */ + public Insets getInsets(Insets insets) { + insets = super.getInsets(insets); + insets.left += lineNumberWidth(); + return insets; + } + + public int getLineNumberJustification() { + return lineNumberJustification; + } + + public void setLineNumberJustification(int justify) { + if (justify == RIGHT_JUSTIFY || justify == LEFT_JUSTIFY) { + lineNumberJustification = justify; + } + } + + /** + * Returns the width, in pixels, of the maximum line number, plus a trailing + * space. + */ + private int lineNumberWidth() { + // + // note: should this be changed to use all nines for the lineCount? + // for example, if the number of rows is 111...999 could be wider + // (in pixels) in a proportionally spaced font... + // + int lineCount = Math.max(getRows(), getLineCount() + 1); + return getFontMetrics(getFont()).stringWidth(lineCount + " "); + } + + // + // NOTE: This method is called every time the cursor blinks... + // so...optimize (later and if possible) for speed... + // + public void paintComponent(Graphics g) { + Insets insets = getInsets(); + + Rectangle clip = g.getClipBounds(); + + g.setColor(getBackground()); // see note in constructor about this... + g.fillRect(clip.x, clip.y, clip.width, clip.height); + + // do the line numbers need redrawn? + if (clip.x < insets.left) { + FontMetrics fm = g.getFontMetrics(); + int fontHeight = fm.getHeight(); + + // starting location at the "top" of the page... + // y is the starting baseline for the font... + // should "font leading" be applied? + int y = fm.getAscent() + insets.top; + + // + // now determine if it is the "top" of the page...or somewhere else + // + int startingLineNumber = ((clip.y + insets.top) / fontHeight) + 1; + + // + // use any one of the following if's: + // + // if (startingLineNumber != 1) + if (y < clip.y) { + // + // not within the clip rectangle...move it... + // determine how many fontHeight's there are between + // y and clip.y...then add that many fontHeights + // + + y = startingLineNumber * fontHeight - (fontHeight - fm.getAscent()); + } + + // + // options: + // . write the number rows in the document (current) + // . write the number of existing lines in the document (to do) + // see getLineCount() + // + // determine which the "drawing" should end... + // add fontHeight: make sure...part of the line number is drawn + // + // could also do this by determining what the last line + // number to draw. + // then the "while" loop whould change accordingly. + // + int yend = y + clip.height + fontHeight; + + // base x position of the line number + int lnxstart = insets.left; + if (lineNumberJustification == LEFT_JUSTIFY) { + // actual starting location of the string of a left + // justified string...it's constant... + // the right justified string "moves"... + lnxstart -= lineNumberWidth(); + } + + g.setColor(getForeground()); + // + // loop until out of the "visible" region... + // + int length = ("" + Math.max(getRows(), getLineCount() + 1)).length(); + while (y < yend) { + // + // options: + // . left justify the line numbers (current) + // . right justify the line number (to do) + // + + if (lineNumberJustification == LEFT_JUSTIFY) { + g.drawString(startingLineNumber + " ", lnxstart, y); + } else { // right justify + String label = padLabel(startingLineNumber, length, true); + g.drawString(label, insets.left - fm.stringWidth(label), y); + } + + y += fontHeight; + startingLineNumber++; + } + } // draw line numbers? + + super.paintComponent(g); + } // paintComponent + + /** + * Create the string for the line number. NOTE: The length param does + * not include the optional space added after the line number. + * + * @param lineNumber + * to stringize + * @param length + * the length desired of the string + * @param length + * the length desired of the string + * + * @return the line number for drawing + */ + private String padLabel(int lineNumber, int length, boolean addSpace) { + StringBuffer buffer = new StringBuffer(); + buffer.append(lineNumber); + for (int count = (length - buffer.length()); count > 0; count--) { + buffer.insert(0, ' '); + } + if (addSpace) { + buffer.append(' '); + } + return buffer.toString(); + } +} diff --git a/mapevaluator/src/main/java/mobac/gui/mapview/LogPreviewMap.java b/mapevaluator/src/main/java/mobac/gui/mapview/LogPreviewMap.java new file mode 100644 index 0000000..efb417e --- /dev/null +++ b/mapevaluator/src/main/java/mobac/gui/mapview/LogPreviewMap.java @@ -0,0 +1,206 @@ +package mobac.gui.mapview; + +import mobac.gui.mapview.layer.MapGridLayer; +import mobac.program.interfaces.HttpMapSource; +import mobac.program.interfaces.MapSourceListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.net.URL; +import java.util.LinkedList; +import java.util.NoSuchElementException; +import java.util.TimerTask; + +public class LogPreviewMap extends PreviewMap { + + private static final Logger LOG = LoggerFactory.getLogger(LogPreviewMap.class); + + private final LinkedList logLines = new LinkedList<>(); + private final Font logFont = new Font("Sans Serif", Font.BOLD, 14); + private final Font tileInfoFont = new Font("Sans Serif", Font.BOLD, 12); + + // private Timer timer = new Timer(); + + public LogPreviewMap() { + super(); + usePlaceHolderTiles = false; + setZoomContolsVisible(true); + setTileGridVisible(true); + setTileGridVisible(true); + // timer.schedule(new LogRemoverTimerTask(), 0, 500); + jobDispatcher.addMapSourceListener(new MapSourceListener() { + @Override + public void tileDownloadStarted(String tileUrl) { + addLog("Downloading " + tileUrl); + } + + @Override + public void tileDownloaded(int size) { + + } + + @Override + public void tileLoadedFromCache(int size) { + + } + }); + } + + @Override + public void setTileGridVisible(boolean tileGridVisible) { + if (isTileGridVisible() == tileGridVisible) { + return; + } + if (tileGridVisible) { + mapGridLayer = new MapGridInfoLayer(); + addMapTileLayers(mapGridLayer); + } else { + removeMapTileLayers(mapGridLayer); + mapGridLayer = null; + } + repaint(); + } + + @Override + protected void paintComponent(Graphics graphics) { + super.paintComponent(graphics); + int y = 18; + graphics.setFont(logFont); + graphics.setColor(Color.RED); + synchronized (logLines) { + for (LogEntry entry : logLines) { + graphics.drawString(entry.msg, 50, y); + y += 20; + } + } + } + + public void addLog(String msg) { + LOG.debug(msg); + LogEntry entry = new LogEntry(); + entry.msg = msg; + synchronized (logLines) { + logLines.addFirst(entry); + if (logLines.size() > 10) { + logLines.removeLast(); + } + } + } + + public static class LogEntry { + final long time = System.currentTimeMillis(); + String msg; + } + + public class LogRemoverTimerTask extends TimerTask { + + @Override + public void run() { + long minTime = System.currentTimeMillis() - 4000; + boolean dirty = false; + try { + synchronized (logLines) { + while (true) { + LogEntry e = logLines.getLast(); + if (e.time < minTime) { + logLines.removeLast(); + dirty = true; + } else { + break; + } + } + } + } catch (NoSuchElementException e) { + } + if (dirty) { + repaint(); + } + } + } + + public class MapGridInfoLayer extends MapGridLayer { + + public void paintTile(Graphics g, int gx, int gy, int tilex, int tiley, int zoom) { + if (tilex < 0 || tiley < 0) { + return; + } + int max = mapSource.getMapSpace().getMaxPixels(zoom); + int tileSize = mapSource.getMapSpace().getTileSize(); + if (tilex * tileSize >= max || tiley * tileSize >= max) { + return; + } + g.setColor(Color.BLACK); + g.drawRect(gx, gy, tileSize, tileSize); + g.setFont(tileInfoFont); + g.setColor(Color.BLUE); + drawStringBG(g, "zoom=" + zoom, gx + 4, gy += 14); + drawStringBG(g, "x=" + tilex, gx + 4, gy += 16); + drawStringBG(g, "y=" + tiley, gx + 4, gy += 16); + String tileUrl = null; + try { + if (mapSource instanceof HttpMapSource) { + tileUrl = ((HttpMapSource) mapSource).getTileUrl(zoom, tilex, tiley); + } + if (tileUrl != null) { + URL url = new URL(tileUrl); + drawUrl(g, "host=" + url.getHost(), gx + 4, gy += 16, tileSize); + drawUrl(g, url.getPath(), gx + 4, gy += 16, tileSize); + + String strQuery = url.getQuery(); + if (strQuery != null && strQuery.length() > 0) { + drawUrl(g, "?" + strQuery, gx + 4, gy += 16, tileSize); + } + } + } catch (Exception e) { + } + } + } + + private void drawUrl(Graphics g, String s, int x, int y, int width) { + FontMetrics fm = g.getFontMetrics(); + int lineHeight = fm.getHeight(); + int ascent = fm.getAscent(); + + int curX = x; + int curY = y; + width -= 15; + + int beginIndex = 0; + for (int i = 0; i < s.length(); i++) { + String sub = s.substring(beginIndex, i); + int textWidth = fm.stringWidth(sub); + if (textWidth >= width) { + g.setColor(Color.WHITE); + g.fillRect(curX - 2, curY - ascent, textWidth + 2, lineHeight); + g.setColor(Color.BLUE); + g.drawString(sub, curX, curY); + curY += lineHeight; + beginIndex = i; + sub = null; + } + } + if (beginIndex != s.length()) { + String sub = s.substring(beginIndex); + g.setColor(Color.WHITE); + int textWidth = fm.stringWidth(sub); + g.fillRect(curX - 2, curY - ascent, textWidth + 2, lineHeight); + g.setColor(Color.BLUE); + g.drawString(sub, curX, curY); + } + } + + protected void drawStringBG(Graphics g, String s, int curX, int curY) { + FontMetrics fm = g.getFontMetrics(); + int lineHeight = fm.getHeight(); + int ascent = fm.getAscent(); + g.setColor(Color.WHITE); + int textWidth = fm.stringWidth(s); + g.fillRect(curX - 2, curY - ascent, textWidth + 2, lineHeight); + g.setColor(Color.BLUE); + g.drawString(s, curX, curY); + } +} diff --git a/mapevaluator/src/main/java/mobac/gui/mapview/ReferenceMapMarker.java b/mapevaluator/src/main/java/mobac/gui/mapview/ReferenceMapMarker.java new file mode 100644 index 0000000..a49d17c --- /dev/null +++ b/mapevaluator/src/main/java/mobac/gui/mapview/ReferenceMapMarker.java @@ -0,0 +1,46 @@ +package mobac.gui.mapview; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Stroke; + +public class ReferenceMapMarker { + + protected static Stroke CIRCLE_STROKE = new BasicStroke(5.0f); + protected static Stroke LINE_STROKE = new BasicStroke(1.0f); + + private final Color circleColor; + private final double lat; + private final double lon; + + public ReferenceMapMarker(Color circleColor, double lat, double lon) { + this.circleColor = circleColor; + this.lat = lat; + this.lon = lon; + } + + public void paint(Graphics2D g, Point position) { + int size_h = 10; + int size = size_h * 2 + 1; + g.setStroke(LINE_STROKE); + g.setColor(Color.BLACK); + g.drawLine(position.x, position.y - size_h, position.x, position.y + size_h); + g.drawLine(position.x - size_h, position.y, position.x + size_h, position.y); + g.setColor(circleColor); + g.setStroke(CIRCLE_STROKE); + g.drawOval(position.x - size_h, position.y - size_h, size, size); + } + + // @Override + public double getLat() { + return lat; + } + + // @Override + public double getLon() { + return lon; + } + +} diff --git a/mapevaluator/src/main/java/mobac/tools/MapSourceCapabilityDetector.java b/mapevaluator/src/main/java/mobac/tools/MapSourceCapabilityDetector.java new file mode 100644 index 0000000..8037fc4 --- /dev/null +++ b/mapevaluator/src/main/java/mobac/tools/MapSourceCapabilityDetector.java @@ -0,0 +1,301 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.tools; + +import mobac.program.interfaces.HttpMapSource; +import mobac.program.interfaces.HttpMapSource.TileUpdate; +import mobac.program.interfaces.MapSpace; +import mobac.program.model.EastNorthCoordinate; +import mobac.program.model.Settings; +import mobac.program.model.TileImageType; +import mobac.utilities.Utilities; +import mobac.utilities.imageio.ImageFormatDetector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.InvocationTargetException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.util.List; +import java.util.Map; + +public class MapSourceCapabilityDetector { + + public static final Logger log = LoggerFactory.getLogger(MapSourceCapabilityDetector.class); + + private final HttpMapSource mapSource; + private final EastNorthCoordinate coordinate; + private final int zoom; + + private URL url; + private HttpURLConnection c; + + private boolean success = false; + private Exception error = null; + + private boolean eTagPresent = false; + private boolean expirationTimePresent = false; + private boolean lastModifiedTimePresent = false; + private boolean ifNoneMatchSupported = false; + private boolean ifModifiedSinceSupported = false; + + private String contentType = "?"; + static final byte[] HEX_CHAR_TABLE = {(byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', + (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', + (byte) 'f'}; + + public MapSourceCapabilityDetector(Class mapSourceClass, EastNorthCoordinate coordinate, + int zoom) + throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { + this(mapSourceClass.getConstructor().newInstance(), coordinate, zoom); + } + + public static String getHexString(byte[] raw) throws UnsupportedEncodingException { + byte[] hex = new byte[2 * raw.length]; + int index = 0; + + for (byte b : raw) { + int v = b & 0xFF; + hex[index++] = HEX_CHAR_TABLE[v >>> 4]; + hex[index++] = HEX_CHAR_TABLE[v & 0xF]; + } + return new String(hex, StandardCharsets.US_ASCII); + } + + public MapSourceCapabilityDetector(HttpMapSource mapSource, EastNorthCoordinate coordinate, int zoom) { + this.mapSource = mapSource; + if (mapSource == null) { + throw new NullPointerException("MapSource not set"); + } + this.coordinate = coordinate; + this.zoom = zoom; + } + + private void testIfNoneMatch(byte[] content) throws Exception { + String eTag = c.getHeaderField("ETag"); + MessageDigest md5 = MessageDigest.getInstance("MD5"); + byte[] digest = md5.digest(content); + String hexDigest = getHexString(digest); + // log.debug("content MD5 : {}", hexDigest); + if (hexDigest.equals(eTag)) { + log.debug("eTag content : md5 hex string"); + } + String quotedHexDigest = "\"" + hexDigest + "\""; + if (quotedHexDigest.equals(eTag)) { + log.debug("eTag content : quoted md5 hex string"); + } + + HttpURLConnection c2 = (HttpURLConnection) url.openConnection(); + c2.addRequestProperty("If-None-Match", eTag); + c2.connect(); + int code = c2.getResponseCode(); + boolean supported = (code == 304); + ifNoneMatchSupported = supported; + // System.out.print("If-None-Match response: "); + // log.debug(b2s(supported) + " - " + code + " (" + + // c2.getResponseMessage() + ")"); + c2.disconnect(); + } + + protected void printHeaders() { + log.trace("\nHeaders:"); + for (Map.Entry> entry : c.getHeaderFields().entrySet()) { + String key = entry.getKey(); + for (String elem : entry.getValue()) { + if (key != null) { + log.debug(key + " = "); + } + log.debug(elem); + } + } + } + + @Override + public String toString() { + StringWriter sw = new StringWriter(); + sw.append("Mapsource.........: " + mapSource.getName() + "\n"); + sw.append("Current TileUpdate: " + mapSource.getTileUpdate() + "\n"); + sw.append("If-None-Match.....: " + b2s(ifNoneMatchSupported) + "\n"); + sw.append("ETag..............: " + b2s(eTagPresent) + "\n"); + sw.append("If-Modified-Since.: " + b2s(ifModifiedSinceSupported) + "\n"); + sw.append("LastModified......: " + b2s(lastModifiedTimePresent) + "\n"); + sw.append("Expires...........: " + b2s(expirationTimePresent) + "\n"); + return sw.toString(); + } + + public boolean isSuccess() { + return success; + } + + public Exception getError() { + return error; + } + + public int getZoom() { + return zoom; + } + + public boolean iseTagPresent() { + return eTagPresent; + } + + public boolean isExpirationTimePresent() { + return expirationTimePresent; + } + + public boolean isLastModifiedTimePresent() { + return lastModifiedTimePresent; + } + + public boolean isIfModifiedSinceSupported() { + return ifModifiedSinceSupported; + } + + public boolean isIfNoneMatchSupported() { + return ifNoneMatchSupported; + } + + public String getContentType() { + return contentType; + } + + public TileUpdate getRecommendedTileUpdate() { + if (ifNoneMatchSupported) { + return TileUpdate.IfNoneMatch; + } + if (ifModifiedSinceSupported) { + return TileUpdate.IfModifiedSince; + } + if (eTagPresent) { + return TileUpdate.ETag; + } + if (lastModifiedTimePresent) { + return TileUpdate.LastModified; + } + return TileUpdate.None; + } + + private static String b2s(boolean b) { + if (b) { + return "supported"; + } else { + return "-"; + } + } + + private void testIfModified() throws IOException { + HttpURLConnection c2 = (HttpURLConnection) url.openConnection(); + c2.setIfModifiedSince(System.currentTimeMillis() + 1000); // future date + c2.connect(); + int code = c2.getResponseCode(); + boolean supported = (code == 304); + ifModifiedSinceSupported = supported; + // System.out.print("If-Modified-Since : "); + // log.debug(b2s(supported) + " - " + code + " (" + + // c2.getResponseMessage() + ")"); + } + + public void testMapSource() { + try { + log.debug("Testing {}", mapSource); + + MapSpace mapSpace = mapSource.getMapSpace(); + int tilex = mapSpace.cLonToX(coordinate.lon, zoom) / mapSpace.getTileSize(); + int tiley = mapSpace.cLatToY(coordinate.lat, zoom) / mapSpace.getTileSize(); + + c = mapSource.getTileUrlConnection(zoom, tilex, tiley); + url = c.getURL(); + log.trace("Sample url: {}", c.getURL()); + log.trace("Connecting..."); + c.setReadTimeout(10000); + Settings settings = Settings.getInstance(); + c.addRequestProperty("User-agent", settings.getUserAgent()); + c.setRequestProperty("Accept", settings.getHttpAccept()); + c.connect(); + log.debug("Connection established - response HTTP {}", c.getResponseCode()); + if (c.getResponseCode() != 200) { + return; + } + + // printHeaders(); + + byte[] content = Utilities.getInputBytes(c.getInputStream()); + TileImageType detectedContentType = ImageFormatDetector.getImageType(content); + + contentType = c.getContentType(); + contentType = contentType.substring(6); + if ("png".equals(contentType)) { + contentType = "png"; + } else if ("jpeg".equals(contentType) || "jpg".equals(contentType)) { + contentType = "jpg"; + } else { + contentType = "unknown: " + c.getContentType(); + } + if (contentType.equals(detectedContentType.getFileExt())) { + contentType += " (verified)"; + } else { + contentType += " (unverified)"; + } + log.debug("Image format : " + contentType); + + String eTag = c.getHeaderField("ETag"); + Utilities.checkForInterruption(); + eTagPresent = (eTag != null); + if (eTagPresent) { + // log.debug("eTag : " + eTag); + testIfNoneMatch(content); + } + // else log.debug("eTag : -"); + + // long date = c.getDate(); + // if (date == 0) + // log.debug("Date time : -"); + // else + // log.debug("Date time : " + new Date(date)); + + long exp = c.getExpiration(); + expirationTimePresent = (c.getHeaderField("expires") != null) && (exp != 0); + if (exp == 0) { + // log.debug("Expiration time : -"); + } else { + // long diff = (exp - System.currentTimeMillis()) / 1000; + // log.debug("Expiration time : " + new Date(exp) + // + " => " + // + Utilities.formatDurationSeconds(diff)); + } + long modified = c.getLastModified(); + lastModifiedTimePresent = (c.getHeaderField("last-modified") != null) && (modified != 0); + // if (modified == 0) + // log.debug("Last modified time : not set"); + // else + // log.debug("Last modified time : " + new + // Date(modified)); + + Utilities.checkForInterruption(); + testIfModified(); + success = true; + } catch (Exception e) { + this.error = e; + log.error("", e); + } + } +} diff --git a/mapevaluator/src/main/java/mobac/tools/MapSourceCapabilityGUI.java b/mapevaluator/src/main/java/mobac/tools/MapSourceCapabilityGUI.java new file mode 100644 index 0000000..d665e4e --- /dev/null +++ b/mapevaluator/src/main/java/mobac/tools/MapSourceCapabilityGUI.java @@ -0,0 +1,171 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.tools; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableCellRenderer; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.HeadlessException; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +public class MapSourceCapabilityGUI extends JFrame implements ActionListener { + + private static final String[] STATUS = {"failed", "success"}; + + private final List result; + + private final JTable table; + + private final JButton button; + + private Thread workerThread = null; + + public MapSourceCapabilityGUI(List result) throws HeadlessException { + super("Map source capabilities"); + setLayout(new BorderLayout()); + this.result = result; + table = new JTable(new Model()); + table.setDefaultRenderer(Object.class, new Renderer()); + table.getColumnModel().getColumn(1).setMaxWidth(100); + button = new JButton("Detection running - abort detection"); + button.addActionListener(this); + add(table.getTableHeader(), BorderLayout.NORTH); + add(table, BorderLayout.CENTER); + add(button, BorderLayout.SOUTH); + setSize(800, 500); + Dimension dScreen = Toolkit.getDefaultToolkit().getScreenSize(); + setLocation((dScreen.width - getWidth()) / 2, (dScreen.height - getHeight()) / 2); + } + + public void refresh() { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + table.revalidate(); + table.repaint(); + } + }); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (workerThread != null) { + workerThread.interrupt(); + } else { + dispose(); + } + } + + public void workerFinished() { + workerThread = null; + button.setText("Close"); + } + + public Thread getWorkerThread() { + return workerThread; + } + + public void setWorkerThread(Thread workerThread) { + this.workerThread = workerThread; + } + + private class Model extends AbstractTableModel { + + public int getRowCount() { + return result.size(); + } + + public Object getValueAt(int rowIndex, int columnIndex) { + + MapSourceCapabilityDetector mscd = result.get(rowIndex); + + switch (columnIndex) { + case 0 : + return STATUS[mscd.isSuccess() ? 1 : 0]; + case 1 : + return mscd.getZoom(); + case 2 : + return mscd.getRecommendedTileUpdate(); + case 3 : + return mscd.iseTagPresent(); + case 4 : + return mscd.isLastModifiedTimePresent(); + case 5 : + return mscd.isIfNoneMatchSupported(); + case 6 : + return mscd.isIfModifiedSinceSupported(); + case 7 : + return mscd.getContentType(); + } + return null; + } + + public int getColumnCount() { + return 8; + } + + public String getColumnName(int column) { + switch (column) { + case 0 : + return "Test"; + case 1 : + return "Zoom"; + case 2 : + return "tileUpdate recommendation"; + case 3 : + return "eTag"; + case 4 : + return "LastModified"; + case 5 : + return "IfNoneMatch"; + case 6 : + return "IfModifiedSince"; + case 7 : + return "Content type"; + } + return null; + } + + } + + private static class Renderer extends DefaultTableCellRenderer { + + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, + int row, int column) { + this.setHorizontalAlignment(JLabel.CENTER); + Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + if ((column > 2) && (value instanceof Boolean) && ((Boolean) value)) { + c.setBackground(Color.GREEN); + } else { + c.setBackground(Color.WHITE); + } + return c; + } + } + +} diff --git a/mapevaluator/src/main/java/org/apache/axis2/description/java2wsdl/bytecode/ClassReader.java b/mapevaluator/src/main/java/org/apache/axis2/description/java2wsdl/bytecode/ClassReader.java new file mode 100644 index 0000000..be6490c --- /dev/null +++ b/mapevaluator/src/main/java/org/apache/axis2/description/java2wsdl/bytecode/ClassReader.java @@ -0,0 +1,467 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.axis2.description.java2wsdl.bytecode; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +/** + * This is the class file reader for obtaining the parameter names for declared + * methods in a class. The class must have debugging attributes for us to obtain + * this information. + *

+ *

+ * This does not work for inherited methods. To obtain parameter names for + * inherited methods, you must use a paramReader for the class that originally + * declared the method. + *

+ *

+ * don't get tricky, it's the bare minimum. Instances of this class are not + * threadsafe -- don't share them. + *

+ */ +public class ClassReader extends ByteArrayInputStream { + // constants values that appear in java class files, + // from jvm spec 2nd ed, section 4.4, pp 103 + private static final int CONSTANT_Class = 7; + private static final int CONSTANT_Fieldref = 9; + private static final int CONSTANT_Methodref = 10; + private static final int CONSTANT_InterfaceMethodref = 11; + private static final int CONSTANT_String = 8; + private static final int CONSTANT_Integer = 3; + private static final int CONSTANT_Float = 4; + private static final int CONSTANT_Long = 5; + private static final int CONSTANT_Double = 6; + private static final int CONSTANT_NameAndType = 12; + private static final int CONSTANT_Utf8 = 1; + + /* + * java 8 9 10 11 new tokens + * https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html + */ + private static final int CONSTANT_MethodHandle = 15; + private static final int CONSTANT_MethodType = 16; + private static final int CONSTANT_Dynamic = 17; + private static final int CONSTANT_InvokeDynamic = 18; + private static final int CONSTANT_Module = 19; + private static final int CONSTANT_Package = 20; + /* end of ava 8 9 10 11 new tokens */ + + /** + * the constant pool. constant pool indices in the class file directly index + * into this array. The value stored in this array is the position in the class + * file where that constant begins. + */ + private int[] cpoolIndex; + private Object[] cpool; + + private final Map attrMethods; + + /** + * Loads the bytecode for a given class, by using the class's defining + * classloader and assuming that for a class named P.C, the bytecodes are in a + * resource named /P/C.class. + * + * @param c + * the class of interest + * @return Returns a byte array containing the bytecode + * @throws IOException + */ + protected static byte[] getBytes(Class c) throws IOException { + InputStream fin = c.getResourceAsStream('/' + c.getName().replace('.', '/') + ".class"); + if (fin == null) { + throw new IOException("Unable to load bytecode for class " + c.getName()); + } + try { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buf = new byte[1024]; + int actual; + do { + actual = fin.read(buf); + if (actual > 0) { + out.write(buf, 0, actual); + } + } while (actual > 0); + return out.toByteArray(); + } finally { + fin.close(); + } + } + + static String classDescriptorToName(String desc) { + return desc.replace('/', '.'); + } + + protected static Map findAttributeReaders(Class c) { + HashMap map = new HashMap(); + Method[] methods = c.getMethods(); + + for (int i = 0; i < methods.length; i++) { + String name = methods[i].getName(); + if (name.startsWith("read") && methods[i].getReturnType() == void.class) { + map.put(name.substring(4), methods[i]); + } + } + + return map; + } + + protected static String getSignature(Member method, Class[] paramTypes) { + // compute the method descriptor + + StringBuffer b = new StringBuffer((method instanceof Method) ? method.getName() : ""); + b.append('('); + + for (int i = 0; i < paramTypes.length; i++) { + addDescriptor(b, paramTypes[i]); + } + + b.append(')'); + if (method instanceof Method) { + addDescriptor(b, ((Method) method).getReturnType()); + } else if (method instanceof Constructor) { + addDescriptor(b, void.class); + } + + return b.toString(); + } + + private static void addDescriptor(StringBuffer b, Class c) { + if (c.isPrimitive()) { + if (c == void.class) { + b.append('V'); + } else if (c == int.class) { + b.append('I'); + } else if (c == boolean.class) { + b.append('Z'); + } else if (c == byte.class) { + b.append('B'); + } else if (c == short.class) { + b.append('S'); + } else if (c == long.class) { + b.append('J'); + } else if (c == char.class) { + b.append('C'); + } else if (c == float.class) { + b.append('F'); + } else if (c == double.class) { + b.append('D'); + } + } else if (c.isArray()) { + b.append('['); + addDescriptor(b, c.getComponentType()); + } else { + b.append('L').append(c.getName().replace('.', '/')).append(';'); + } + } + + /** + * @return Returns the next unsigned 16 bit value. + */ + protected final int readShort() { + return (read() << 8) | read(); + } + + /** + * @return Returns the next signed 32 bit value. + */ + protected final int readInt() { + return (read() << 24) | (read() << 16) | (read() << 8) | read(); + } + + /** + * Skips n bytes in the input stream. + */ + protected void skipFully(int n) throws IOException { + while (n > 0) { + int c = (int) skip(n); + if (c == 0) { + throw new EOFException("Error looking for paramter names in bytecode: unexpected end of file"); + } + n -= c; + } + } + + protected final Member resolveMethod(int index) throws IOException, ClassNotFoundException, NoSuchMethodException { + int oldPos = pos; + try { + Member m = (Member) cpool[index]; + if (m == null) { + pos = cpoolIndex[index]; + Class owner = resolveClass(readShort()); + NameAndType nt = resolveNameAndType(readShort()); + String signature = nt.name + nt.type; + if (nt.name.equals("")) { + Constructor[] ctors = owner.getConstructors(); + for (int i = 0; i < ctors.length; i++) { + String sig = getSignature(ctors[i], ctors[i].getParameterTypes()); + if (sig.equals(signature)) { + cpool[index] = m = ctors[i]; + return m; + } + } + } else { + Method[] methods = owner.getDeclaredMethods(); + for (int i = 0; i < methods.length; i++) { + String sig = getSignature(methods[i], methods[i].getParameterTypes()); + if (sig.equals(signature)) { + cpool[index] = m = methods[i]; + return m; + } + } + } + throw new NoSuchMethodException(signature); + } + return m; + } finally { + pos = oldPos; + } + + } + + protected final Field resolveField(int i) throws IOException, ClassNotFoundException, NoSuchFieldException { + int oldPos = pos; + try { + Field f = (Field) cpool[i]; + if (f == null) { + pos = cpoolIndex[i]; + Class owner = resolveClass(readShort()); + NameAndType nt = resolveNameAndType(readShort()); + cpool[i] = f = owner.getDeclaredField(nt.name); + } + return f; + } finally { + pos = oldPos; + } + } + + private static class NameAndType { + String name; + String type; + + public NameAndType(String name, String type) { + this.name = name; + this.type = type; + } + } + + protected final NameAndType resolveNameAndType(int i) throws IOException { + int oldPos = pos; + try { + NameAndType nt = (NameAndType) cpool[i]; + if (nt == null) { + pos = cpoolIndex[i]; + String name = resolveUtf8(readShort()); + String type = resolveUtf8(readShort()); + cpool[i] = nt = new NameAndType(name, type); + } + return nt; + } finally { + pos = oldPos; + } + } + + protected final Class resolveClass(int i) throws IOException, ClassNotFoundException { + int oldPos = pos; + try { + Class c = (Class) cpool[i]; + if (c == null) { + pos = cpoolIndex[i]; + String name = resolveUtf8(readShort()); + cpool[i] = c = Class.forName(classDescriptorToName(name)); + } + return c; + } finally { + pos = oldPos; + } + } + + protected ClassReader(byte[] buf, Map attrMethods) { + super(buf); + + this.attrMethods = attrMethods; + } + + protected final void readCpool() throws IOException { + int count = readShort(); // cpool count + cpoolIndex = new int[count]; + cpool = new Object[count]; + for (int i = 1; i < count; i++) { + int c = read(); + cpoolIndex[i] = super.pos; + switch (c) { // constant pool tag + case CONSTANT_Fieldref : + case CONSTANT_Methodref : + case CONSTANT_InterfaceMethodref : + case CONSTANT_NameAndType : + + readShort(); // class index or (12) name index + // fall through + + case CONSTANT_Class : + case CONSTANT_String : + + readShort(); // string index or class index + break; + + case CONSTANT_Long : + case CONSTANT_Double : + + readInt(); // hi-value + + // see jvm spec section 4.4.5 - double and long cpool + // entries occupy two "slots" in the cpool table. + i++; + // fall through + + case CONSTANT_Integer : + case CONSTANT_Float : + + readInt(); // value + break; + + case CONSTANT_Utf8 : + + int len = readShort(); + skipFully(len); + break; + + case CONSTANT_MethodHandle : + + read(); // reference kind + readShort(); // reference index + break; + + case CONSTANT_MethodType : + + readShort(); // descriptor index + break; + case CONSTANT_Dynamic : + readShort(); // bootstrap method attr index + readShort(); // name and type index + break; + case CONSTANT_InvokeDynamic : + + readShort(); // bootstrap method attr index + readShort(); // name and type index + break; + + default : + // corrupt class file + throw new IllegalStateException( + "Error looking for parameter names in bytecode: unexpected bytes in file"); + } + } + } + + protected final void skipAttributes() throws IOException { + int count = readShort(); + for (int i = 0; i < count; i++) { + readShort(); // name index + skipFully(readInt()); + } + } + + protected final String resolveUtf8(int i) throws IOException { + int oldPos = pos; + try { + String s = (String) cpool[i]; + if (s == null) { + pos = cpoolIndex[i]; + int len = readShort(); + skipFully(len); + cpool[i] = s = new String(buf, pos - len, len, StandardCharsets.UTF_8); + } + return s; + } finally { + pos = oldPos; + } + } + + /** + * Reads a code attribute. + * + * @throws IOException + */ + public void readCode() throws IOException { + readShort(); // max stack + readShort(); // max locals + skipFully(readInt()); // code + skipFully(8 * readShort()); // exception table + + // read the code attributes (recursive). This is where + // we will find the LocalVariableTable attribute. + readAttributes(); + } + + /** + * Reads an attributes array. The elements of a class file that can contain + * attributes are: fields, methods, the class itself, and some other types of + * attributes. + */ + protected final void readAttributes() throws IOException { + int count = readShort(); + for (int i = 0; i < count; i++) { + int nameIndex = readShort(); // name index + int attrLen = readInt(); + int curPos = pos; + + String attrName = resolveUtf8(nameIndex); + + Method m = attrMethods.get(attrName); + + if (m != null) { + try { + m.invoke(this); + } catch (IllegalAccessException e) { + pos = curPos; + skipFully(attrLen); + } catch (InvocationTargetException e) { + try { + throw e.getTargetException(); + } catch (Error ex) { + throw ex; + } catch (RuntimeException ex) { + throw ex; + } catch (IOException ex) { + throw ex; + } catch (Throwable ex) { + pos = curPos; + skipFully(attrLen); + } + } + } else { + // don't care what attribute this is + skipFully(attrLen); + } + } + } +} diff --git a/mapevaluator/src/main/java/org/apache/axis2/description/java2wsdl/bytecode/ParamReader.java b/mapevaluator/src/main/java/org/apache/axis2/description/java2wsdl/bytecode/ParamReader.java new file mode 100644 index 0000000..b81ab89 --- /dev/null +++ b/mapevaluator/src/main/java/org/apache/axis2/description/java2wsdl/bytecode/ParamReader.java @@ -0,0 +1,224 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.axis2.description.java2wsdl.bytecode; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; + +/** + * This is the class file reader for obtaining the parameter names for declared + * methods in a class. The class must have debugging attributes for us to obtain + * this information. + *

+ *

+ * This does not work for inherited methods. To obtain parameter names for + * inherited methods, you must use a paramReader for the class that originally + * declared the method. + *

+ *

+ * don't get tricky, it's the bare minimum. Instances of this class are not + * threadsafe -- don't share them. + *

+ */ +public class ParamReader extends ClassReader { + private String methodName; + private final Map methods = new HashMap<>(); + private Class[] paramTypes; + + /** + * Processes a class file, given it's class. We'll use the defining classloader + * to locate the bytecode. + * + * @param c + * @throws IOException + */ + public ParamReader(Class c) throws IOException { + this(getBytes(c)); + } + + /** + * Processes the given class bytes directly. + * + * @param b + * @throws IOException + */ + public ParamReader(byte[] b) throws IOException { + super(b, findAttributeReaders(ParamReader.class)); + + // check the magic number + if (readInt() != 0xCAFEBABE) { + // not a class file! + throw new IOException( + "Error looking for paramter names in bytecode: input does not appear to be a valid class file"); + } + + readShort(); // minor version + readShort(); // major version + + readCpool(); // slurp in the constant pool + + readShort(); // access flags + readShort(); // this class name + readShort(); // super class name + + int count = readShort(); // ifaces count + for (int i = 0; i < count; i++) { + readShort(); // interface index + } + + count = readShort(); // fields count + for (int i = 0; i < count; i++) { + readShort(); // access flags + readShort(); // name index + readShort(); // descriptor index + skipAttributes(); // field attributes + } + + count = readShort(); // methods count + for (int i = 0; i < count; i++) { + readShort(); // access flags + int m = readShort(); // name index + String name = resolveUtf8(m); + int d = readShort(); // descriptor index + this.methodName = name + resolveUtf8(d); + readAttributes(); // method attributes + } + + } + + public void readCode() throws IOException { + readShort(); // max stack + int maxLocals = readShort(); // max locals + + MethodInfo info = new MethodInfo(maxLocals); + if (methodName != null) { + methods.put(methodName, info); + } + + skipFully(readInt()); // code + skipFully(8 * readShort()); // exception table + // read the code attributes (recursive). This is where + // we will find the LocalVariableTable attribute. + readAttributes(); + } + + /** + * Returns the names of the declared parameters for the given constructor. If we + * cannot determine the names, return null. The returned array will have one + * name per parameter. The length of the array will be the same as the length of + * the Class[] array returned by Constructor.getParameterTypes(). + * + * @param ctor + * @return Returns String[] array of names, one per parameter, or null + */ + public String[] getParameterNames(Constructor ctor) { + paramTypes = ctor.getParameterTypes(); + return getParameterNames(ctor, paramTypes); + } + + /** + * Returns the names of the declared parameters for the given method. If we + * cannot determine the names, return null. The returned array will have one + * name per parameter. The length of the array will be the same as the length of + * the Class[] array returned by Method.getParameterTypes(). + * + * @param method + * @return Returns String[] array of names, one per parameter, or null + */ + public String[] getParameterNames(Method method) { + paramTypes = method.getParameterTypes(); + return getParameterNames(method, paramTypes); + } + + protected String[] getParameterNames(Member member, Class[] paramTypes) { + // look up the names for this method + MethodInfo info = methods.get(getSignature(member, paramTypes)); + + // we know all the local variable names, but we only need to return + // the names of the parameters. + + if (info != null) { + String[] paramNames = new String[paramTypes.length]; + int j = Modifier.isStatic(member.getModifiers()) ? 0 : 1; + + boolean found = false; // did we find any non-null names + for (int i = 0; i < paramNames.length; i++) { + if (info.names[j] != null) { + found = true; + paramNames[i] = info.names[j]; + } + j++; + if (paramTypes[i] == double.class || paramTypes[i] == long.class) { + // skip a slot for 64bit params + j++; + } + } + + if (found) { + return paramNames; + } else { + return null; + } + } else { + return null; + } + } + + private static class MethodInfo { + String[] names; + + public MethodInfo(int maxLocals) { + names = new String[maxLocals]; + } + } + + private MethodInfo getMethodInfo() { + MethodInfo info = null; + if (methodName != null) { + info = methods.get(methodName); + } + return info; + } + + /** + * This is invoked when a LocalVariableTable attribute is encountered. + * + * @throws IOException + */ + public void readLocalVariableTable() throws IOException { + int len = readShort(); // table length + MethodInfo info = getMethodInfo(); + for (int j = 0; j < len; j++) { + readShort(); // start pc + readShort(); // length + int nameIndex = readShort(); // name_index + readShort(); // descriptor_index + int index = readShort(); // local index + if (info != null) { + info.names[index] = resolveUtf8(nameIndex); + } + } + } +} diff --git a/mapevaluator/src/main/resources/mobac/mobac.properties b/mapevaluator/src/main/resources/mobac/mobac.properties new file mode 100644 index 0000000..be001ba --- /dev/null +++ b/mapevaluator/src/main/resources/mobac/mobac.properties @@ -0,0 +1 @@ +mobac.revision.hide=true \ No newline at end of file diff --git a/mapevaluator/src/main/resources/mobac/resources/bsh/default.bsh b/mapevaluator/src/main/resources/mobac/resources/bsh/default.bsh new file mode 100644 index 0000000..8abd2f6 --- /dev/null +++ b/mapevaluator/src/main/resources/mobac/resources/bsh/default.bsh @@ -0,0 +1,22 @@ +/** + OpenStreetMap Example: + Input parameters for this script: "zoom", "x" and "y" +**/ +String getTileUrl( int zoom, int x, int y ) { + return "https://tileserver.4umaps.com/" + zoom + "/" + x + "/" + y + ".png"; +} +void addHeaders( java.net.HttpURLConnection conn) { + // Optional: set HTTP Referer or Cookies + conn.addRequestProperty("Cookie","test=12345"); + conn.addRequestProperty("Referer","http://www.openstreetmap.org"); +} + +tileType = "png"; // required - image format "png" "jpg" or "gif" + +// Default size of each tile is 256x256 pixel +tileSize = 256; // optional +minZoom = 0; // optional +maxZoom = 22; // optional + +tileUpdate = TileUpdate.None; // optional - possibilities: +// TileUpdate.IfNoneMatch, TileUpdate.ETag, TileUpdate.IfModifiedSince, TileUpdate.LastModified, TileUpdate.None \ No newline at end of file diff --git a/mapevaluator/src/main/resources/mobac/resources/bsh/empty.bsh b/mapevaluator/src/main/resources/mobac/resources/bsh/empty.bsh new file mode 100644 index 0000000..71110f8 --- /dev/null +++ b/mapevaluator/src/main/resources/mobac/resources/bsh/empty.bsh @@ -0,0 +1,7 @@ +String getTileUrl( int zoom, int x, int y ) { + return ""; +} +void addHeaders( java.net.HttpURLConnection conn ) { + // conn.addRequestProperty("header-name","vale"); +} +tileType = ""; \ No newline at end of file diff --git a/mapevaluator/src/main/resources/mobac/resources/bsh/osm.bsh b/mapevaluator/src/main/resources/mobac/resources/bsh/osm.bsh new file mode 100644 index 0000000..f6338b8 --- /dev/null +++ b/mapevaluator/src/main/resources/mobac/resources/bsh/osm.bsh @@ -0,0 +1,10 @@ +/** + OpenStreetMap Example: + Input parameters for this script: "zoom", "x" and "y" +**/ +String getTileUrl( int zoom, int x, int y ) { + baseUrl = "https://tileserver.4umaps.com/"; // maps4u + return baseUrl + zoom + "/" + x + "/" + y + ".png"; +} +tileType = "png"; +tileUpdate = TileUpdate.IfModifiedSince; \ No newline at end of file diff --git a/mapevaluator/src/main/resources/mobac/resources/images/capabilities-icon.png b/mapevaluator/src/main/resources/mobac/resources/images/capabilities-icon.png new file mode 100644 index 0000000..770ebe0 Binary files /dev/null and b/mapevaluator/src/main/resources/mobac/resources/images/capabilities-icon.png differ diff --git a/mapevaluator/src/main/resources/mobac/resources/images/check-icon.png b/mapevaluator/src/main/resources/mobac/resources/images/check-icon.png new file mode 100644 index 0000000..4c564a7 Binary files /dev/null and b/mapevaluator/src/main/resources/mobac/resources/images/check-icon.png differ diff --git a/mapevaluator/src/main/resources/mobac/resources/images/google-icon.png b/mapevaluator/src/main/resources/mobac/resources/images/google-icon.png new file mode 100644 index 0000000..813ae0d Binary files /dev/null and b/mapevaluator/src/main/resources/mobac/resources/images/google-icon.png differ diff --git a/mapevaluator/src/main/resources/mobac/resources/images/help-icon.png b/mapevaluator/src/main/resources/mobac/resources/images/help-icon.png new file mode 100644 index 0000000..af34a63 Binary files /dev/null and b/mapevaluator/src/main/resources/mobac/resources/images/help-icon.png differ diff --git a/mapevaluator/src/main/resources/mobac/resources/images/icons.txt b/mapevaluator/src/main/resources/mobac/resources/images/icons.txt new file mode 100644 index 0000000..0cc61b0 --- /dev/null +++ b/mapevaluator/src/main/resources/mobac/resources/images/icons.txt @@ -0,0 +1,9 @@ +Toolbar Icons by Ruby Software + http://www.iconshut.com/application-icons/1186-toolbar-icons.html + +help-icon: + http://commons.wikimedia.org/wiki/File:Torchlight_help_icon.svg + +capabilities-icon.png: + Scrap Icons By Deleket Application Icons + http://www.iconshut.com/application-icons/1166-scrap-icons.html diff --git a/mapevaluator/src/main/resources/mobac/resources/images/info-icon.png b/mapevaluator/src/main/resources/mobac/resources/images/info-icon.png new file mode 100644 index 0000000..98e0574 Binary files /dev/null and b/mapevaluator/src/main/resources/mobac/resources/images/info-icon.png differ diff --git a/mapevaluator/src/main/resources/mobac/resources/images/new-icon.png b/mapevaluator/src/main/resources/mobac/resources/images/new-icon.png new file mode 100644 index 0000000..cd9b6eb Binary files /dev/null and b/mapevaluator/src/main/resources/mobac/resources/images/new-icon.png differ diff --git a/mapevaluator/src/main/resources/mobac/resources/images/open-icon.png b/mapevaluator/src/main/resources/mobac/resources/images/open-icon.png new file mode 100644 index 0000000..4deeeb2 Binary files /dev/null and b/mapevaluator/src/main/resources/mobac/resources/images/open-icon.png differ diff --git a/mapevaluator/src/main/resources/mobac/resources/images/osm-icon.png b/mapevaluator/src/main/resources/mobac/resources/images/osm-icon.png new file mode 100644 index 0000000..e4cd392 Binary files /dev/null and b/mapevaluator/src/main/resources/mobac/resources/images/osm-icon.png differ diff --git a/mapevaluator/src/main/resources/mobac/resources/images/save-icon.png b/mapevaluator/src/main/resources/mobac/resources/images/save-icon.png new file mode 100644 index 0000000..f652aeb Binary files /dev/null and b/mapevaluator/src/main/resources/mobac/resources/images/save-icon.png differ diff --git a/mappacks/build.gradle b/mappacks/build.gradle new file mode 100644 index 0000000..26768ee --- /dev/null +++ b/mappacks/build.gradle @@ -0,0 +1,45 @@ +plugins { +} +subprojects { + apply plugin: 'java' + apply plugin: 'at.bxm.svntools' + + dependencies { + compileOnly project(':mobac') + + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.0' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' + } + + jar { + archiveFileName = "mp-${project.name}.jar" + manifest { + attributes "MapPackVersion": "1" + attributes "MapPackName": "${project.name}" + attributes "MapPackBuild-Date": new Date().toString() + attributes "MapPackRevision": "$svntools.info.revisionNumber" + } + doLast { + def keystore = file("${rootProject.projectDir}/keys/keystore.jks") + if (keystore.exists()) { + def keystoreProps = new Properties() + file("${rootProject.projectDir}/keys/keystore.properties").withInputStream { keystoreProps.load(it) } + println("Signing map pack ${project.name}") + ant.signjar( + jar: "build/libs/mp-${project.name}.jar", + destDir: "build/libs/", + alias: "mappack", + storetype: "jks", + keystore: "${rootProject.projectDir}/keys/keystore.jks", + storepass: keystoreProps.getProperty("keystore.password"), + verbose: false, + preservelastmodified: "true" + ) + } + } + } + + test { + useJUnitPlatform() + } +} \ No newline at end of file diff --git a/mappacks/openstreetmap/build.gradle b/mappacks/openstreetmap/build.gradle new file mode 100644 index 0000000..e69de29 diff --git a/mappacks/openstreetmap/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource b/mappacks/openstreetmap/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource new file mode 100644 index 0000000..219f3d0 --- /dev/null +++ b/mappacks/openstreetmap/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource @@ -0,0 +1,4 @@ +mobac.mapsources.mappacks.openstreetmap.Hikebikemap +#mobac.mapsources.mappacks.openstreetmap.Osm4uMaps +mobac.mapsources.mappacks.openstreetmap.OsmPublicTransport +mobac.mapsources.mappacks.openstreetmap.WanderreitkarteAbo diff --git a/mappacks/region_america_north/build.gradle b/mappacks/region_america_north/build.gradle new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/mobac/mapsources/mappacks/region_america_north/mapsources.list b/mappacks/region_america_north/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource similarity index 60% rename from src/main/java/mobac/mapsources/mappacks/region_america_north/mapsources.list rename to mappacks/region_america_north/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource index 304b040..fa8f5ff 100644 --- a/src/main/java/mobac/mapsources/mappacks/region_america_north/mapsources.list +++ b/mappacks/region_america_north/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource @@ -1,9 +1,14 @@ +mobac.mapsources.mappacks.region_america_north.CanadaToporama mobac.mapsources.mappacks.region_america_north.ChartbundleENRA mobac.mapsources.mappacks.region_america_north.ChartbundleENRH mobac.mapsources.mappacks.region_america_north.ChartbundleENRL mobac.mapsources.mappacks.region_america_north.ChartbundleSEC mobac.mapsources.mappacks.region_america_north.ChartbundleTAC -mobac.mapsources.mappacks.region_america_north.ChartbundleWAC +mobac.mapsources.mappacks.region_america_north.ChartbundleHC mobac.mapsources.mappacks.region_america_north.USNationalMapImagery mobac.mapsources.mappacks.region_america_north.USNationalMapImageryTopo mobac.mapsources.mappacks.region_america_north.USNationalMapTopo +mobac.mapsources.mappacks.region_america_north.USNationalMapRelief +mobac.mapsources.mappacks.region_america_north.ThunderforestOutdoors +mobac.mapsources.mappacks.region_america_north.ThunderforestLandscape + diff --git a/mappacks/region_europe/build.gradle b/mappacks/region_europe/build.gradle new file mode 100644 index 0000000..e69de29 diff --git a/mappacks/region_europe/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource b/mappacks/region_europe/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource new file mode 100644 index 0000000..4dca029 --- /dev/null +++ b/mappacks/region_europe/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource @@ -0,0 +1,3 @@ +mobac.mapsources.mappacks.region_europe.IgnBase +mobac.mapsources.mappacks.region_europe.IgnMtmRaster +mobac.mapsources.mappacks.region_europe.IgnPnoa \ No newline at end of file diff --git a/mappacks/region_europe_east/build.gradle b/mappacks/region_europe_east/build.gradle new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/mobac/mapsources/mappacks/region_europe_east/mapsources.list b/mappacks/region_europe_east/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource similarity index 50% rename from src/main/java/mobac/mapsources/mappacks/region_europe_east/mapsources.list rename to mappacks/region_europe_east/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource index c16a020..ce4a636 100644 --- a/src/main/java/mobac/mapsources/mappacks/region_europe_east/mapsources.list +++ b/mappacks/region_europe_east/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource @@ -2,7 +2,4 @@ mobac.mapsources.mappacks.region_europe_east.UmpWawPl mobac.mapsources.mappacks.region_europe_east.FreemapSlovakia mobac.mapsources.mappacks.region_europe_east.FreemapSlovakiaCycling mobac.mapsources.mappacks.region_europe_east.FreemapSlovakiaHiking -mobac.mapsources.mappacks.region_europe_east.MoldovaPointMd -mobac.mapsources.mappacks.region_europe_east.Turaterkep -mobac.mapsources.mappacks.region_europe_east.OSMapaTopo -mobac.mapsources.mappacks.region_europe_east.OSMapaTopoContours +mobac.mapsources.mappacks.region_europe_east.Turaterkep \ No newline at end of file diff --git a/mappacks/region_oceania/build.gradle b/mappacks/region_oceania/build.gradle new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/mobac/mapsources/mappacks/region_oceania/mapsources.list b/mappacks/region_oceania/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource similarity index 100% rename from src/main/java/mobac/mapsources/mappacks/region_oceania/mapsources.list rename to mappacks/region_oceania/src/main/resources/META-INF/services/mobac.program.interfaces.MapSource diff --git a/mapsources-updates/mappacks-md5.txt b/mapsources-updates/mappacks-md5.txt new file mode 100644 index 0000000..eff1f07 --- /dev/null +++ b/mapsources-updates/mappacks-md5.txt @@ -0,0 +1,5 @@ +0ee7558c3f16f4c20595688832111f61 mp-region_oceania.jar +4a9e05897159ab4a7b49fed221d6cdd1 mp-openstreetmap.jar +2e6ca98b3f49a6b9a69d454acceb9696 mp-region_america_north.jar +dbeb826768bb0cfdc0307a6e88016186 mp-region_europe_east.jar +aa39059d9abb94b99d2a2f084d54179f mp-region_europe.jar diff --git a/mapsources-updates/mp-openstreetmap.jar b/mapsources-updates/mp-openstreetmap.jar new file mode 100644 index 0000000..b7fdd00 Binary files /dev/null and b/mapsources-updates/mp-openstreetmap.jar differ diff --git a/mapsources-updates/mp-region_america_north.jar b/mapsources-updates/mp-region_america_north.jar new file mode 100644 index 0000000..ab0cc81 Binary files /dev/null and b/mapsources-updates/mp-region_america_north.jar differ diff --git a/mapsources-updates/mp-region_europe.jar b/mapsources-updates/mp-region_europe.jar new file mode 100644 index 0000000..9e65c00 Binary files /dev/null and b/mapsources-updates/mp-region_europe.jar differ diff --git a/mapsources-updates/mp-region_europe_east.jar b/mapsources-updates/mp-region_europe_east.jar new file mode 100644 index 0000000..8b80710 Binary files /dev/null and b/mapsources-updates/mp-region_europe_east.jar differ diff --git a/mapsources-updates/mp-region_oceania.jar b/mapsources-updates/mp-region_oceania.jar new file mode 100644 index 0000000..d2f205d Binary files /dev/null and b/mapsources-updates/mp-region_oceania.jar differ diff --git a/misc/Incompatible maps.txt b/misc/Incompatible maps.txt new file mode 100644 index 0000000..3bffea5 --- /dev/null +++ b/misc/Incompatible maps.txt @@ -0,0 +1,74 @@ +Ireland Map + http://ims0.osiemaps.ie/website/publicviewer/main.aspx?id=&utype=&ecom=S1&user= + Reason: Wrong tile size (512x512) + +Mapy.cz + http://www.mapy.cz/ + Reason: Incompatible zoom levels + +SwissGeo + http://www.swissgeo.ch/surf.php + Reason: Wrong tile size (400x400) + +Enrio.se + http://kartor.eniro.se/ + Reason: Incompatible zoom levels + +OpenSeaMap: + http://www.openseamap.org/ + Reason: map is only an overlay to OSM Mapnik + +Topo Schweiz + www.gps-tracks.com + Reason: Wrong tile size (200x200) + +Topo Deutschland + www.gps-tracks.com + Reason: Wrong tile size (400x400) + +Topo Österreich + www.gps-tracks.com + Reason: Wrong tile size (200x200) + +Centrum.cz + http://amapy.centrum.cz + Reason: Wrong projection + +Mapy.sk + http://mapy.atlas.sk + Reason: Wrong tile size (250x250) + +Géoportail + http://www.geoportail.fr/5069711/visu2D/afficher-en-2d.htm + Reason: Incompatible zoom levels + +Asplan Viak Internet AS + http://kart.kystverket.no/advanced_default.aspx?lang=eng + Reason: Unsupported projection: "Universal Transverse Mercator" (UTM) + +Japanese Topo Maps + http://watchizu.gsi.go.jp/watchizu.html?meshcode=49324455 + Reason: Unsupported tile size (300x357) + +ICC Catalunya + http://cygnus.icc.cat/mt10m/ + http://cygnus.icc.cat/bt5m/ + Reason: different projection (Plate Carrée projection based on Latitude / Longitude WGS 84) + +Zumi Poland + http://mapy.zumi.pl/ + Reson: Tile size 250x250 + +Hungarian Turistautak.hu + http://www.turistautak.hu/maps.php?id=magyarorszag&image=raster + Reson: Tile size 410x300 + +Mapa Polski Targeo + http://mapa.targeo.pl/ + Reson: Tile size 200x200 + + NASA World Wind + Reason: Incompatible projection, incompatible tile size (512x512) + + Mapplus.ch / Map+ + Reason: License problem with swisstopo \ No newline at end of file diff --git a/misc/external tools/SAXCount.exe b/misc/external tools/SAXCount.exe new file mode 100644 index 0000000..4218547 Binary files /dev/null and b/misc/external tools/SAXCount.exe differ diff --git a/misc/external tools/TBMapper.exe b/misc/external tools/TBMapper.exe new file mode 100644 index 0000000..5fd4fdd Binary files /dev/null and b/misc/external tools/TBMapper.exe differ diff --git a/misc/external tools/tweakpng.exe b/misc/external tools/tweakpng.exe new file mode 100644 index 0000000..da66280 Binary files /dev/null and b/misc/external tools/tweakpng.exe differ diff --git a/misc/external tools/validate-gpx.cmd b/misc/external tools/validate-gpx.cmd new file mode 100644 index 0000000..c629a0c --- /dev/null +++ b/misc/external tools/validate-gpx.cmd @@ -0,0 +1 @@ +SaxCount.exe -v=always -n -s -f %1 \ No newline at end of file diff --git a/misc/external tools/xerces-c_2_8.dll b/misc/external tools/xerces-c_2_8.dll new file mode 100644 index 0000000..49b9a85 Binary files /dev/null and b/misc/external tools/xerces-c_2_8.dll differ diff --git a/misc/launch4j.xml b/misc/launch4j.xml deleted file mode 100644 index 061fbe9..0000000 --- a/misc/launch4j.xml +++ /dev/null @@ -1,35 +0,0 @@ - - true - gui - Mobile_Atlas_Creator.jar - ..\Mobile Atlas Creator.exe - - - - normal - http://java.com/download - - false - false - - mobac.ico - - - 1.6.0_14 - - preferJre - 1024 - - - 1.0.0.0 - - - Mobile Atlas Creator Windows Launcher - MOBAC developers - 1.0.0.0 - - - Mobile Atlas Creator - - Mobile Atlas Creator 1024MB max Heap - Mobile Atlas Creator.exe - - \ No newline at end of file diff --git a/misc/mobac.icns b/misc/mobac.icns new file mode 100644 index 0000000..70c90fd Binary files /dev/null and b/misc/mobac.icns differ diff --git a/misc/samples/gpx/gpx10 route.gpx b/misc/samples/gpx/gpx10 route.gpx new file mode 100644 index 0000000..728185d --- /dev/null +++ b/misc/samples/gpx/gpx10 route.gpx @@ -0,0 +1,50 @@ + + + + + + GPX1.1 Route A + + Route A - P1 + + + Route A - P2 + + + Route A - P3 + + + Route A - P4 + + + Route A - P5 + + + Route A - P6 + + + Route A - P7 + + + + GPX1.1 Route B + + Route B - P1 + + + Route B - P2 + + + Route B - P3 + + + Route B - P4 + + + Route B - P5 + + + \ No newline at end of file diff --git a/misc/samples/gpx/gpx10 track.gpx b/misc/samples/gpx/gpx10 track.gpx new file mode 100644 index 0000000..9306202 --- /dev/null +++ b/misc/samples/gpx/gpx10 track.gpx @@ -0,0 +1,27 @@ + + + + + + gpx10 track + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/misc/samples/gpx/gpx10 wpt.gpx b/misc/samples/gpx/gpx10 wpt.gpx new file mode 100644 index 0000000..3df5f12 --- /dev/null +++ b/misc/samples/gpx/gpx10 wpt.gpx @@ -0,0 +1,68 @@ + + + + + + Route A - P1 + Route A - P1 + Route A - P1 + + + Route A - P2 + Route A - P2 + Route A - P2 + + + Route A - P3 + Route A - P3 + Route A - P3 + + + Route A - P4 + Route A - P4 + Route A - P4 + + + Route A - P5 + Route A - P5 + Route A - P5 + + + Route A - P6 + Route A - P6 + Route A - P6 + + + Route A - P7 + Route A - P7 + Route A - P7 + + + Route B - P1 + Route B - P1 + Route B - P1 + + + Route B - P2 + Route B - P2 + Route B - P2 + + + Route B - P3 + Route B - P3 + Route B - P3 + + + Route B - P4 + Route B - P4 + Route B - P4 + + + Route B - P5 + Route B - P5 + Route B - P5 + + \ No newline at end of file diff --git a/misc/samples/gpx/gpx11 empty.gpx b/misc/samples/gpx/gpx11 empty.gpx new file mode 100644 index 0000000..709598d --- /dev/null +++ b/misc/samples/gpx/gpx11 empty.gpx @@ -0,0 +1,2 @@ + + diff --git a/misc/samples/gpx/gpx11 round track.gpx b/misc/samples/gpx/gpx11 round track.gpx new file mode 100644 index 0000000..16f165b --- /dev/null +++ b/misc/samples/gpx/gpx11 round track.gpx @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/misc/samples/gpx/gpx11 route.gpx b/misc/samples/gpx/gpx11 route.gpx new file mode 100644 index 0000000..1797edf --- /dev/null +++ b/misc/samples/gpx/gpx11 route.gpx @@ -0,0 +1,47 @@ + + + + GPX1.1 Route A + + Route A - P1 + + + Route A - P2 + + + Route A - P3 + + + Route A - P4 + + + Route A - P5 + + + Route A - P6 + + + Route A - P7 + + + + GPX1.1 Route B + + Route B - P1 + + + Route B - P2 + + + Route B - P3 + + + Route B - P4 + + + Route B - P5 + + + \ No newline at end of file diff --git a/misc/samples/gpx/gpx11 track.gpx b/misc/samples/gpx/gpx11 track.gpx new file mode 100644 index 0000000..34aa718 --- /dev/null +++ b/misc/samples/gpx/gpx11 track.gpx @@ -0,0 +1,17 @@ + + + + gpx10 track + + + + + + + + + + + \ No newline at end of file diff --git a/misc/samples/gpx/gpx11 wpt.gpx b/misc/samples/gpx/gpx11 wpt.gpx new file mode 100644 index 0000000..4a5cbcc --- /dev/null +++ b/misc/samples/gpx/gpx11 wpt.gpx @@ -0,0 +1,70 @@ + + + + + + Route A - P1 + Route A - P1 + Route A - P1 + + + Route A - P2 + Route A - P2 + Route A - P2 + + + Route A - P3 + Route A - P3 + Route A - P3 + + + Route A - P4 + Route A - P4 + Route A - P4 + + + Route A - P5 + Route A - P5 + Route A - P5 + + + Route A - P6 + Route A - P6 + Route A - P6 + + + Route A - P7 + Route A - P7 + Route A - P7 + + + Route B - P1 + Route B - P1 + Route B - P1 + + + Route B - P2 + Route B - P2 + Route B - P2 + + + Route B - P3 + Route B - P3 + Route B - P3 + + + Route B - P4 + Route B - P4 + Route B - P4 + + + Route B - P5 + Route B - P5 + Route B - P5 + + diff --git a/misc/samples/gpx/mystic_basin_trail.gpx b/misc/samples/gpx/mystic_basin_trail.gpx new file mode 100644 index 0000000..32fed27 --- /dev/null +++ b/misc/samples/gpx/mystic_basin_trail.gpx @@ -0,0 +1,1917 @@ + + + + + + +trails@topografix.com + + + + + + + 13.106400 + + + + + Scenic Area + + + + + + + Shopping Center + + + + + + + + + Boat Ramp + + + + 10.698480 + + + + Scenic Area + + + + + + + Dot + + + + + + Dot + + + + + + + Bridge + + + + + + + Park + + + + 10.942320 + + + + + Dam + + + + 6.370320 + + + + + Anchor + + + + + + + Trail Head + + + + + + + + + Shopping Center + + + + 8.778240 + + + + + Tall Tower + + + + + + + Parking Area + + + + + + + Bridge + + + + + + + Bridge + + + + + + + Building + + + + + + + Swimming Area + + + + + + + + + Park + + + + + + + Boat Ramp + + + + + + Danger Area + + + + + + + + + RV Park + + + + + + + Boat Ramp + + + + + + + + 1 + 71b33c + + + + + Trail Head + + + + + + + + + + + Swimming Area + + + + + + + + + Boat Ramp + + + + + + + + + + + Dot + + + + + + + + + + + Boat Ramp + + + + + + + + + + + Park + + + + 10.942320 + + + + + Dam + + + + 10.698480 + + + + Scenic Area + + + + + + + Bridge + + + + + + + Boat Ramp + + + + + + + + + + Danger Area + + + + + + + Boat Ramp + + + + + + + + + + Dot + + + + + + + + + + + Parking Area + + + + + + + + 6.370320 + + + + + Anchor + + + + + + + + 8.778240 + + + + + Tall Tower + + + + + + + + + + + Bridge + + + + + + + + + + + Trail Head + + + + + + + 3 + 00d7ff + + + + + Trail Head + + + + + + + Swimming Area + + + + + + + + + Boat Ramp + + + + + + + Bridge + + + + 6.370320 + + + + + Anchor + + + + 8.778240 + + + + + Tall Tower + + + + + + + Bridge + + + + + + + Trail Head + + + + + + + 2 + 00ff00 + + + 19.363770 + + Waypoint + + + 18.883057 + + Waypoint + + + 17.921753 + + Waypoint + + + 16.479736 + + Waypoint + + + 15.518433 + + Waypoint + + + 15.037720 + + Waypoint + + + 15.037720 + + Waypoint + + + 15.037720 + + Waypoint + + + 14.557007 + + Waypoint + + + 14.557007 + + Waypoint + + + 14.557007 + + Waypoint + + + 14.557007 + + Waypoint + + + 14.076416 + + Waypoint + + + 13.595825 + + Waypoint + + + 13.595825 + + Waypoint + + + 14.076416 + + Waypoint + + + 14.076416 + + Waypoint + + + 14.557007 + + Waypoint + + + 15.518433 + + Waypoint + + + 14.557007 + + Waypoint + + + 14.076416 + + Waypoint + + + 13.115112 + + Waypoint + + + 13.595825 + + Waypoint + + + 13.595825 + + Waypoint + + + 13.595825 + + Waypoint + + + 13.115112 + + Waypoint + + + 13.115112 + + Waypoint + + + 13.595825 + + Waypoint + + + 13.595825 + + Waypoint + + + 13.595825 + + Waypoint + + + 13.115112 + + Waypoint + + + 13.115112 + + Waypoint + + + 14.076416 + + Waypoint + + + 12.634399 + + Waypoint + + + 12.153809 + + Waypoint + + + 11.192505 + + Waypoint + + + 10.711792 + + Waypoint + + + 10.711792 + + Waypoint + + + 10.711792 + + Waypoint + + + 10.711792 + + Waypoint + + + 10.231201 + + Waypoint + + + 9.269897 + + Waypoint + + + 8.789185 + + Waypoint + + + 9.750610 + + Waypoint + + + 9.750610 + + Waypoint + + + 10.231201 + + Waypoint + + + 9.750610 + + Waypoint + + + 10.231201 + + Waypoint + + + 10.231201 + + Waypoint + + + 10.231201 + + Waypoint + + + 10.711792 + + Waypoint + + + 10.711792 + + Waypoint + + + 11.192505 + + Waypoint + + + 11.192505 + + Waypoint + + + 11.192505 + + Waypoint + + + 12.153809 + + Waypoint + + + 12.634399 + + Waypoint + + + 12.634399 + + Waypoint + + + 13.115112 + + Waypoint + + + 13.115112 + + Waypoint + + + 12.634399 + + Waypoint + + + 12.153809 + + Waypoint + + + 12.153809 + + Waypoint + + + 12.153809 + + Waypoint + + + 12.153809 + + Waypoint + + + 11.673218 + + Waypoint + + + 11.673218 + + Waypoint + + + 9.750610 + + Waypoint + + + 9.269897 + + Waypoint + + + 10.231201 + + Waypoint + + + 10.231201 + + Waypoint + + + 10.231201 + + Waypoint + + + 10.711792 + + Waypoint + + + 10.231201 + + Waypoint + + + 10.231201 + + Waypoint + + + 9.750610 + + Waypoint + + + 10.231201 + + Waypoint + + + 9.750610 + + Waypoint + + + 9.750610 + + Waypoint + + + 10.231201 + + Waypoint + + + 11.673218 + + Waypoint + + + 13.115112 + + Waypoint + + + 14.557007 + + Waypoint + + + 15.518433 + + Waypoint + + + 15.999023 + + Waypoint + + + 14.557007 + + Waypoint + + + 13.115112 + + Waypoint + + + 12.634399 + + Waypoint + + + 12.634399 + + Waypoint + + + 11.673218 + + Waypoint + + + 12.153809 + + Waypoint + + + 12.153809 + + Waypoint + + + 11.673218 + + Waypoint + + + 11.192505 + + Waypoint + + + 11.192505 + + Waypoint + + + 11.673218 + + Waypoint + + + 11.192505 + + Waypoint + + + 11.192505 + + Waypoint + + + 11.673218 + + Waypoint + + + 10.711792 + + Waypoint + + + 10.231201 + + Waypoint + + + 10.231201 + + Waypoint + + + 9.750610 + + Waypoint + + + 8.789185 + + Waypoint + + + 9.269897 + + Waypoint + + + 9.269897 + + Waypoint + + + 9.750610 + + Waypoint + + + 10.231201 + + Waypoint + + + 9.750610 + + Waypoint + + + 9.269897 + + Waypoint + + + 10.231201 + + Waypoint + + + 10.711792 + + Waypoint + + + 11.192505 + + Waypoint + + + 10.711792 + + Waypoint + + + 10.711792 + + Waypoint + + + 11.192505 + + Waypoint + + + 11.673218 + + Waypoint + + + 12.153809 + + Waypoint + + + 12.153809 + + Waypoint + + + 12.634399 + + Waypoint + + + 11.673218 + + Waypoint + + + 11.192505 + + Waypoint + + + 10.711792 + + Waypoint + + + 11.673218 + + Waypoint + + + 11.673218 + + Waypoint + + + 12.153809 + + Waypoint + + + 12.153809 + + Waypoint + + + 12.634399 + + Waypoint + + + 12.153809 + + Waypoint + + + 10.711792 + + Waypoint + + + 10.711792 + + Waypoint + + + 11.192505 + + Waypoint + + + 10.711792 + + Waypoint + + + 11.192505 + + Waypoint + + + 11.192505 + + Waypoint + + + 10.231201 + + Waypoint + + + 9.750610 + + Waypoint + + + 9.269897 + + Waypoint + + + 9.750610 + + Waypoint + + + 9.750610 + + Waypoint + + + 10.231201 + + Waypoint + + + 11.673218 + + Waypoint + + + 10.711792 + + Waypoint + + + 9.269897 + + Waypoint + + + 9.269897 + + Waypoint + + + 9.269897 + + Waypoint + + + 10.231201 + + Waypoint + + + 10.231201 + + Waypoint + + + 9.269897 + + Waypoint + + + 9.750610 + + Waypoint + + + 9.269897 + + Waypoint + + + 8.789185 + + Waypoint + + + 7.827881 + + Waypoint + + + 8.308594 + + Waypoint + + + 8.308594 + + Waypoint + + + 8.308594 + + Waypoint + + + 8.789185 + + Waypoint + + + 8.789185 + + Waypoint + + + 9.269897 + + Waypoint + + + 10.711792 + + Waypoint + + + 12.634399 + + Waypoint + + + 13.595825 + + Waypoint + + + 14.076416 + + Waypoint + + + 14.076416 + + Waypoint + + + 13.595825 + + Waypoint + + + 13.115112 + + Waypoint + + + + + + + + + 4 + 00ffff + + + 42.916016 + + Waypoint + + + 37.148071 + + Waypoint + + + 35.225464 + + Waypoint + + + 31.380127 + + Waypoint + + + 28.976929 + + Waypoint + + + 28.496216 + + Waypoint + + + 27.054321 + + Waypoint + + + 25.131714 + + Waypoint + + + 23.689575 + + Waypoint + + + 21.766968 + + Waypoint + + + 20.805664 + + Waypoint + + + 19.363770 + + Waypoint + + + 17.921753 + + Waypoint + + + 16.960449 + + Waypoint + + + 15.999023 + + Waypoint + + + 14.557007 + + Waypoint + + + 13.115112 + + Waypoint + + + 10.711792 + + Waypoint + + + 10.711792 + + Waypoint + + + 10.711792 + + Waypoint + + + 9.750610 + + Waypoint + + + 9.269897 + + Waypoint + + + 9.269897 + + Waypoint + + + 8.789185 + + Waypoint + + + 8.789185 + + Waypoint + + + 7.827881 + + Waypoint + + + 8.308594 + + Waypoint + + + 7.827881 + + Waypoint + + + 7.347168 + + Waypoint + + + 6.866455 + + Waypoint + + + 6.866455 + + Waypoint + + + 6.866455 + + Waypoint + + + 5.905273 + + Waypoint + + + 6.866455 + + Waypoint + + + 8.308594 + + Waypoint + + + 9.750610 + + Waypoint + + + 10.231201 + + Waypoint + + + 9.269897 + + Waypoint + + + 8.308594 + + Waypoint + + + 8.308594 + + Waypoint + + + 7.827881 + + Waypoint + + + 8.308594 + + Waypoint + + + 7.827881 + + Waypoint + + + 7.827881 + + Waypoint + + + 8.308594 + + Waypoint + + + 7.827881 + + Waypoint + + + 8.308594 + + Waypoint + + + 8.789185 + + Waypoint + + + 8.789185 + + Waypoint + + + 8.308594 + + Waypoint + + + 8.308594 + + Waypoint + + + 7.827881 + + Waypoint + + + 7.347168 + + Waypoint + + + 7.347168 + + Waypoint + + + 7.347168 + + Waypoint + + + 5.905273 + + Waypoint + + + 6.385864 + + Waypoint + + + 5.905273 + + Waypoint + + + 5.905273 + + Waypoint + + + 6.866455 + + Waypoint + + + 5.905273 + + Waypoint + + + 5.905273 + + Waypoint + + + 5.905273 + + Waypoint + + + 5.905273 + + Waypoint + + + 6.385864 + + Waypoint + + + 7.347168 + + Waypoint + + + 7.347168 + + Waypoint + + + 7.347168 + + Waypoint + + + 7.827881 + + Waypoint + + + 7.827881 + + Waypoint + + + 6.866455 + + Waypoint + + + 6.385864 + + Waypoint + + + 6.866455 + + Waypoint + + + 7.347168 + + Waypoint + + + 7.827881 + + Waypoint + + + 7.347168 + + Waypoint + + + 6.866455 + + Waypoint + + + 6.866455 + + Waypoint + + + 7.347168 + + Waypoint + + + 8.789185 + + Waypoint + + + 7.347168 + + Waypoint + + + 7.827881 + + Waypoint + + + 7.347168 + + Waypoint + + + 6.385864 + + Waypoint + + + 5.905273 + + Waypoint + + + 5.905273 + + Waypoint + + + 5.905273 + + Waypoint + + + 6.385864 + + Waypoint + + + 6.866455 + + Waypoint + + + 7.827881 + + Waypoint + + + 10.231201 + + Waypoint + + + 11.673218 + + Waypoint + + + 11.673218 + + Waypoint + + + 11.192505 + + Waypoint + + + 9.750610 + + Waypoint + + + + + + + 5 + 800080 + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 48.683960 + + Waypoint + + + 46.761230 + + Waypoint + + + + + \ No newline at end of file diff --git a/misc/xml-schemas/gpx_1_0.xsd b/misc/xml-schemas/gpx_1_0.xsd new file mode 100644 index 0000000..63d4640 --- /dev/null +++ b/misc/xml-schemas/gpx_1_0.xsd @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/misc/xml-schemas/gpx_1_1.xsd b/misc/xml-schemas/gpx_1_1.xsd new file mode 100644 index 0000000..b270eb5 --- /dev/null +++ b/misc/xml-schemas/gpx_1_1.xsd @@ -0,0 +1,775 @@ + + + + + + + + + GPX documents contain a metadata header, followed by waypoints, routes, and tracks. You can add your own elements + to the extensions section of the GPX document. + + + + + + + Metadata about the file. + + + + + + + A list of waypoints. + + + + + + + A list of routes. + + + + + + + A list of tracks. + + + + + + + You can add extend GPX by adding your own elements from another schema here. + + + + + + + + + You must include the version number in your GPX document. + + + + + + + You must include the name or URL of the software that created your GPX document. This allows others to + inform the creator of a GPX instance document that fails to validate. + + + + + + + + + + Information about the GPX file, author, and copyright restrictions goes in the metadata section. Providing rich, + meaningful information about your GPX files allows others to search for and use your GPS data. + + + + + + + The name of the GPX file. + + + + + + + A description of the contents of the GPX file. + + + + + + + The person or organization who created the GPX file. + + + + + + + Copyright and license information governing use of the file. + + + + + + + URLs associated with the location described in the file. + + + + + + + The creation date of the file. + + + + + + + Keywords associated with the file. Search engines or databases can use this information to classify the data. + + + + + + + Minimum and maximum coordinates which describe the extent of the coordinates in the file. + + + + + + + + You can add extend GPX by adding your own elements from another schema here. + + + + + + + + + + wpt represents a waypoint, point of interest, or named feature on a map. + + + + + + + + Elevation (in meters) of the point. + + + + + + + Creation/modification timestamp for element. Date and time in are in Univeral Coordinated Time (UTC), not local time! Conforms to ISO 8601 specification for date/time representation. Fractional seconds are allowed for millisecond timing in tracklogs. + + + + + + + Magnetic variation (in degrees) at the point + + + + + + + Height (in meters) of geoid (mean sea level) above WGS84 earth ellipsoid. As defined in NMEA GGA message. + + + + + + + + + The GPS name of the waypoint. This field will be transferred to and from the GPS. GPX does not place restrictions on the length of this field or the characters contained in it. It is up to the receiving application to validate the field before sending it to the GPS. + + + + + + + GPS waypoint comment. Sent to GPS as comment. + + + + + + + A text description of the element. Holds additional information about the element intended for the user, not the GPS. + + + + + + + Source of data. Included to give user some idea of reliability and accuracy of data. "Garmin eTrex", "USGS quad Boston North", e.g. + + + + + + + Link to additional information about the waypoint. + + + + + + + Text of GPS symbol name. For interchange with other programs, use the exact spelling of the symbol as displayed on the GPS. If the GPS abbreviates words, spell them out. + + + + + + + Type (classification) of the waypoint. + + + + + + + + + Type of GPX fix. + + + + + + + Number of satellites used to calculate the GPX fix. + + + + + + + Horizontal dilution of precision. + + + + + + + Vertical dilution of precision. + + + + + + + Position dilution of precision. + + + + + + + Number of seconds since last DGPS update. + + + + + + + ID of DGPS station used in differential correction. + + + + + + + + You can add extend GPX by adding your own elements from another schema here. + + + + + + + + + The latitude of the point. Decimal degrees, WGS84 datum. + + + + + + + The latitude of the point. Decimal degrees, WGS84 datum. + + + + + + + + + rte represents route - an ordered list of waypoints representing a series of turn points leading to a destination. + + + + + + + GPS name of route. + + + + + + + GPS comment for route. + + + + + + + Text description of route for user. Not sent to GPS. + + + + + + + Source of data. Included to give user some idea of reliability and accuracy of data. + + + + + + + Links to external information about the route. + + + + + + + GPS route number. + + + + + + + Type (classification) of route. + + + + + + + + You can add extend GPX by adding your own elements from another schema here. + + + + + + + + A list of route points. + + + + + + + + + + trk represents a track - an ordered list of points describing a path. + + + + + + + GPS name of track. + + + + + + + GPS comment for track. + + + + + + + User description of track. + + + + + + + Source of data. Included to give user some idea of reliability and accuracy of data. + + + + + + + Links to external information about track. + + + + + + + GPS track number. + + + + + + + Type (classification) of track. + + + + + + + + You can add extend GPX by adding your own elements from another schema here. + + + + + + + + A Track Segment holds a list of Track Points which are logically connected in order. To represent a single GPS track where GPS reception was lost, or the GPS receiver was turned off, start a new Track Segment for each continuous span of track data. + + + + + + + + + + You can add extend GPX by adding your own elements from another schema here. + + + + + + + You can add extend GPX by adding your own elements from another schema here. + + + + + + + + + + A Track Segment holds a list of Track Points which are logically connected in order. To represent a single GPS track where GPS reception was lost, or the GPS receiver was turned off, start a new Track Segment for each continuous span of track data. + + + + + + + A Track Point holds the coordinates, elevation, timestamp, and metadata for a single point in a track. + + + + + + + + You can add extend GPX by adding your own elements from another schema here. + + + + + + + + + + Information about the copyright holder and any license governing use of this file. By linking to an appropriate license, + you may place your data into the public domain or grant additional usage rights. + + + + + + + Year of copyright. + + + + + + + Link to external file containing license text. + + + + + + + + Copyright holder (TopoSoft, Inc.) + + + + + + + + + A link to an external resource (Web page, digital photo, video clip, etc) with additional information. + + + + + + + Text of hyperlink. + + + + + + + Mime type of content (image/jpeg) + + + + + + + + URL of hyperlink. + + + + + + + + + An email address. Broken into two parts (id and domain) to help prevent email harvesting. + + + + + + id half of email address (billgates2004) + + + + + + + domain half of email address (hotmail.com) + + + + + + + + + A person or organization. + + + + + + + Name of person or organization. + + + + + + + Email address. + + + + + + + Link to Web site or other external information about person. + + + + + + + + + + A geographic point with optional elevation and time. Available for use by other schemas. + + + + + + + The elevation (in meters) of the point. + + + + + + + The time that the point was recorded. + + + + + + + + The latitude of the point. Decimal degrees, WGS84 datum. + + + + + + + The latitude of the point. Decimal degrees, WGS84 datum. + + + + + + + + + An ordered sequence of points. (for polygons or polylines, e.g.) + + + + + + + Ordered list of geographic points. + + + + + + + + + + Two lat/lon pairs defining the extent of an element. + + + + + + The minimum latitude. + + + + + + + The minimum longitude. + + + + + + + The maximum latitude. + + + + + + + The maximum longitude. + + + + + + + + + + The latitude of the point. Decimal degrees, WGS84 datum. + + + + + + + + + + + + The longitude of the point. Decimal degrees, WGS84 datum. + + + + + + + + + + + + Used for bearing, heading, course. Units are decimal degrees, true (not magnetic). + + + + + + + + + + + + Type of GPS fix. none means GPS had no fix. To signify "the fix info is unknown, leave out fixType entirely. pps = military signal used + + + + + + + + + + + + + + + Represents a differential GPS station. + + + + + + + + + diff --git a/misc/xml-schemas/ogc_kml22.xsd b/misc/xml-schemas/ogc_kml22.xsd new file mode 100644 index 0000000..1d4aa76 --- /dev/null +++ b/misc/xml-schemas/ogc_kml22.xsd @@ -0,0 +1,1642 @@ + + + + + ogckml22.xsd 2008-01-23 + XML Schema Document for OGC KML version 2.2. Copyright (c) + 2008 Open Geospatial Consortium, Inc. All Rights Reserved. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + not anyURI due to $[x] substitution in + PhotoOverlay + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Snippet deprecated in 2.2 + + + + + + + + + + + + + Metadata deprecated in 2.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Metadata deprecated in 2.2 + + + + + + MetadataType deprecated in 2.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + is the root element. + + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Url deprecated in 2.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Url deprecated in 2.2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + color deprecated in 2.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mobac-run/build.gradle b/mobac-run/build.gradle new file mode 100644 index 0000000..78767bc --- /dev/null +++ b/mobac-run/build.gradle @@ -0,0 +1,18 @@ +plugins { + id 'java' + id 'distribution' +} + +dependencies { + implementation project(':mobac') + implementation project(':mappacks:openstreetmap') + implementation project(':mappacks:region_america_north') + implementation project(':mappacks:region_europe') + implementation project(':mappacks:region_europe_east') + implementation project(':mappacks:region_oceania') + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.0' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' +} +test { + useJUnitPlatform() +} diff --git a/mobac-run/src/main/java/mobac/StartMOBACdev.java b/mobac-run/src/main/java/mobac/StartMOBACdev.java new file mode 100644 index 0000000..92815ef --- /dev/null +++ b/mobac-run/src/main/java/mobac/StartMOBACdev.java @@ -0,0 +1,12 @@ +package mobac; + +/** + * This is just a convenience class for starting MOBAC including mappacks the + * easy way. + */ +public class StartMOBACdev { + + public static void main(String[] args) { + StartMOBAC.main(args); + } +} diff --git a/mobac.icns b/mobac.icns new file mode 100644 index 0000000..70c90fd Binary files /dev/null and b/mobac.icns differ diff --git a/mobac/build.gradle b/mobac/build.gradle new file mode 100644 index 0000000..a53045c --- /dev/null +++ b/mobac/build.gradle @@ -0,0 +1,106 @@ +plugins { + id 'java-library' + id 'edu.sc.seis.launch4j' version '3.0.5' +} + +dependencies { + def mapsforgeVersion = '0.20.0' + // def mapsforgeVersion = 'master-SNAPSHOT' + + implementation "org.mapsforge:mapsforge-core:${mapsforgeVersion}" + implementation "org.mapsforge:mapsforge-map:${mapsforgeVersion}" + implementation "org.mapsforge:mapsforge-map-awt:${mapsforgeVersion}" + implementation "org.mapsforge:mapsforge-map-reader:${mapsforgeVersion}" + implementation "org.mapsforge:mapsforge-themes:${mapsforgeVersion}" + api 'org.apache-extras.beanshell:bsh:2.0b6' + api 'commons-codec:commons-codec:1.15' + api 'commons-io:commons-io:2.11.0' + api 'org.apache.commons:commons-lang3:3.12.0' + api 'org.apache.commons:commons-text:1.9' + api 'com.github.kerner1000:javapng:2.1.2' + api 'org.xerial:sqlite-jdbc:3.43.0.0' + api 'com.sleepycat:je:5.0.73' + api 'org.glassfish.jaxb:jaxb-runtime:3.0.2' + api 'org.slf4j:slf4j-api:1.7.36' + implementation 'com.twelvemonkeys.imageio:imageio-webp:3.9.4' + implementation 'ch.qos.logback:logback-classic:1.2.11' + implementation 'org.slf4j:jul-to-slf4j:1.7.36' + implementation 'net.sf.jtidy:jtidy:r938' + implementation 'com.itextpdf:itextpdf:5.1.3' + implementation 'javax.media:jai-core:1.1.3' + implementation 'com.sun.media:jai-codec:1.1.3' + testImplementation 'org.jboss.resteasy:tjws:2.3.10.Final' + testImplementation 'junit:junit:4.13.2' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2' + testImplementation 'javax.servlet:servlet-api:2.5' + + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2' +} +processResources { + doLast { + def targetDir = new File(sourceSets.main.output.resourcesDir, "mobac") + targetDir.mkdirs() + def props = new Properties() + props.setProperty("mobac.revision", "$svnRevision") + props.setProperty("mobac.version", project.rootProject.version.toString()) + new File(targetDir, "mobac-rev.properties").withWriter { props.store(it, null) } + } +} +jar { + println("SVN revision $svnRevision") + + manifest { + attributes 'Main-Class': 'mobac.StartMOBAC' + attributes 'Version': project.rootProject.version + attributes 'SVN-Revision': svnRevision + attributes 'Build-Timestamp': new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(new Date()) + + // This entry is required by jaxb-runtime to work properly on Java 16+ - otherwise you will encounter + // java.lang.NullPointerException: Cannot invoke "java.lang.reflect.Method.invoke(Object, Object[])" because + // "com.sun.xml.bind.v2.runtime.reflect.opt.Injector.defineClass" is null + attributes 'Multi-Release': 'true' + + attributes 'Add-Exports': 'java.base/sun.net.www.protocol.http java.base/sun.net.www.protocol.https' + } + getArchiveBaseName().set('Mobile_Atlas_Creator') + from { + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + } + exclude("module-info.class") + exclude("META-INF/*.txt") + exclude("META-INF/*.md") + exclude("META-INF/MANIFEST.MF") + exclude("META-INF/maven/*") + // We only support 64 bit common architectures and platforms, remove the rest + exclude("org/sqlite/native/Windows/x86/**") + exclude("org/sqlite/native/Windows/armv7/**") + exclude("org/sqlite/native/Linux/arm*/**") + exclude("org/sqlite/native/Linux/x86/**") + exclude("org/sqlite/native/Linux/ppc64/**") + exclude("org/sqlite/native/Linux-Musl/**") + exclude("org/sqlite/native/Linux-Android/**") + exclude("org/sqlite/native/FreeBSD/**") + duplicatesStrategy DuplicatesStrategy.EXCLUDE +} + +launch4j { + productName = "Mobile Atlas Creator" + fileDescription = "Mobile Atlas Creator Windows Launcher" + // only take the number+dot part at the beginning + version = project.rootProject.version.toString().replaceAll('^([0-9\\.]+).*', '$1') + textVersion = project.rootProject.version + copyright = "MOBAC developers" + companyName = "" + icon = "${projectDir}/launch4j/mobac.ico" + downloadUrl = "https://mobac.sourceforge.io/OpenJDK/" + jreMinVersion = '1.11.0' + requires64Bit = true + dontWrapJar = true + libraryDir = "" + copyConfigurable = [] //["${project.buildDir}/libs/Mobile_Atlas_Creator.jar"] + outfile = "Mobile Atlas Creator.exe" +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/mobac/launch4j/mobac.ico b/mobac/launch4j/mobac.ico new file mode 100644 index 0000000..f946ccf Binary files /dev/null and b/mobac/launch4j/mobac.ico differ diff --git a/src/main/java/mobac/Main.java b/mobac/src/main/java/mobac/Main.java similarity index 82% rename from src/main/java/mobac/Main.java rename to mobac/src/main/java/mobac/Main.java index a906ab5..f9e4aac 100644 --- a/src/main/java/mobac/Main.java +++ b/mobac/src/main/java/mobac/Main.java @@ -1,25 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac; -import javax.imageio.ImageIO; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; - import mobac.gui.MainGUI; import mobac.gui.SplashFrame; import mobac.mapsources.DefaultMapSourcesManager; @@ -29,14 +25,17 @@ import mobac.program.Logging; import mobac.program.ProgramInfo; import mobac.program.commandline.CommandLineEmpty; import mobac.program.commandline.CreateAtlas; +import mobac.program.commandline.PrintPublicKeyHash; +import mobac.program.download.TileDownLoader; import mobac.program.interfaces.CommandLineAction; import mobac.program.model.Settings; import mobac.program.tilestore.TileStore; import mobac.utilities.GUIExceptionHandler; -/** - * Java 6 version of the main starter class - */ +import javax.imageio.ImageIO; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + public class Main { protected CommandLineAction cmdAction = new CommandLineEmpty(); @@ -44,8 +43,9 @@ public class Main { public Main() { try { parseCommandLine(); - if (cmdAction.showSplashScreen()) + if (cmdAction.showSplashScreen()) { SplashFrame.showFrame(); + } DirectoryManager.initialize(); Logging.configureLogging(); @@ -53,9 +53,13 @@ public class Main { // MySocketImplFactory.install(); ProgramInfo.initialize(); // Load revision info Logging.logSystemInfo(); + + cmdAction.afterBasicInitialization(); + GUIExceptionHandler.installToolkitEventQueueProxy(); // Logging.logSystemProperties(); ImageIO.setUseCache(false); + TileDownLoader.init(); EnvironmentSetup.checkFileSetup(); Settings.loadOrQuit(); @@ -83,19 +87,6 @@ public class Main { } } - protected void parseCommandLine() { - String[] args = StartMOBAC.ARGS; - if (args.length >= 2) { - if ("create".equalsIgnoreCase(args[0])) { - if (args.length > 2) - cmdAction = new CreateAtlas(args[1], args[2]); - else - cmdAction = new CreateAtlas(args[1]); - return; - } - } - } - /** * Start MOBAC without Java Runtime version check */ @@ -107,4 +98,20 @@ public class Main { GUIExceptionHandler.processException(t); } } + + protected void parseCommandLine() { + String[] args = StartMOBAC.ARGS; + if (args.length >= 2) { + if (PrintPublicKeyHash.CMD_ARG.equalsIgnoreCase(args[0])) { + cmdAction = new PrintPublicKeyHash(args[1]); + } else if (CreateAtlas.CMD_ARG.equalsIgnoreCase(args[0])) { + if (args.length > 2) { + cmdAction = new CreateAtlas(args[1], args[2]); + } else { + cmdAction = new CreateAtlas(args[1]); + } + return; + } + } + } } diff --git a/src/main/java/mobac/StartMOBAC.java b/mobac/src/main/java/mobac/StartMOBAC.java similarity index 56% rename from src/main/java/mobac/StartMOBAC.java rename to mobac/src/main/java/mobac/StartMOBAC.java index ac54a27..1034558 100644 --- a/src/main/java/mobac/StartMOBAC.java +++ b/mobac/src/main/java/mobac/StartMOBAC.java @@ -1,33 +1,36 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac; import javax.swing.JOptionPane; import javax.swing.UIManager; -import mobac.utilities.I18nUtils; - /** * Main class for starting Mobile Atlas Creator. - * - * This class performs the Java Runtime version check and if the correct version is installed it creates a new instance - * of the class specified by {@link #MAIN_CLASS}. The class to be instantiated is specified by it's name intentionally - * as this allows to compile this class without any further class dependencies. - * + *

+ * This class performs the Java Runtime version check and if the correct version + * is installed it creates a new instance of the class specified by + * {@link #MAIN_CLASS}. The class to be instantiated is specified by it's name + * intentionally as this allows to compile this class without any further class + * dependencies. + *

+ * Note: Translation of Strings in this file do not make sense because the + * settings are not loaded yet. Therefore all messages are always shown in the + * default language. */ public class StartMOBAC { @@ -43,29 +46,31 @@ public class StartMOBAC { setLookAndFeel(); checkVersion(); try { - Class.forName(MAIN_CLASS).newInstance(); + Class.forName(MAIN_CLASS).getConstructor().newInstance(); } catch (Exception e) { e.printStackTrace(); - JOptionPane.showMessageDialog(null, I18nUtils.localizedStringForKey("msg_environment_unable_to_start") + e.getMessage(), - I18nUtils.localizedStringForKey("Error"), + JOptionPane.showMessageDialog(null, "Unable to start Mobile Atlas Creator: \n" + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); + System.exit(1); } } public static void setLookAndFeel() { try { - if (System.getProperty("swing.defaultlaf") != null) + if (System.getProperty("swing.defaultlaf") != null) { return; + } UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - //MainGUI.setDefaultFontOfAllUIComponents(MainGUI.customFont()); + // MainGUI.setDefaultFontOfAllUIComponents(MainGUI.customFont()); } catch (Exception e) { } } protected static void checkVersion() { String ver = System.getProperty("java.specification.version"); - if (ver == null) + if (ver == null) { ver = "Unknown"; + } String[] v = ver.split("\\."); int major = 0; int minor = 0; @@ -75,14 +80,16 @@ public class StartMOBAC { } catch (Exception e) { } int version = (major * 1000) + minor; - // 1.5 -> 1005; 1.6 -> 1006; 1.7 -> 1007 - if (version < 1006) { + // 1.5 -> 1005; 1.6 -> 1006; 1.7 -> 1007; 1.8 -> 1008 + // 11 -> 11000; 12 -> 12000 + if (version < 11000) { JOptionPane.showMessageDialog(null, - String.format(I18nUtils.localizedStringForKey("msg_environment_jre_bellow"), ver), - I18nUtils.localizedStringForKey("msg_environment_jre_bellow_title"), - JOptionPane.ERROR_MESSAGE); + "The used Java Runtime Environment does not meet the minimum requirements.\n\n" + + "Mobile Atlas Creator requires at least Java 11 or higher.\n" + + "Please update your Java Runtime before starting Mobile Atlas Creator.\n\n" + + "Detected Java Runtime Version: " + ver, + "Java Runtime version problem detected", JOptionPane.ERROR_MESSAGE); System.exit(1); } } - } diff --git a/src/main/java/mobac/data/gpx/GPXUtils.java b/mobac/src/main/java/mobac/data/gpx/GPXUtils.java similarity index 68% rename from src/main/java/mobac/data/gpx/GPXUtils.java rename to mobac/src/main/java/mobac/data/gpx/GPXUtils.java index e2b65f7..27f28b8 100644 --- a/src/main/java/mobac/data/gpx/GPXUtils.java +++ b/mobac/src/main/java/mobac/data/gpx/GPXUtils.java @@ -1,70 +1,51 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.data.gpx; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStream; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBException; +import jakarta.xml.bind.Marshaller; +import jakarta.xml.bind.Unmarshaller; +import jakarta.xml.bind.util.JAXBResult; +import mobac.data.gpx.gpx11.Gpx; +import mobac.utilities.Utilities; +import org.w3c.dom.Document; -import javax.swing.JOptionPane; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; -import javax.xml.bind.util.JAXBResult; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamSource; - -import mobac.data.gpx.gpx11.Gpx; -import mobac.program.Logging; -import mobac.utilities.Utilities; - -import org.w3c.dom.Document; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; public class GPXUtils { - public static boolean checkJAXBVersion() { - boolean res = Utilities.checkJAXBVersion(); - if (!res) - JOptionPane.showMessageDialog(null, - "Outdated Java Runtime Environment and JAXB version", - "Mobile Atlas Creator has detected that your used " - + "Java Runtime Environment is too old.\n Please update " - + "the Java Runtime Environment to at least \nversion " - + "1.6.0_14 and restart Mobile Atlas Creator.", - JOptionPane.ERROR_MESSAGE); - return res; - } - public static Gpx loadGpxFile(File f) throws JAXBException { // Create GPX 1.1 JAXB context JAXBContext context = JAXBContext.newInstance(Gpx.class); Unmarshaller unmarshaller = context.createUnmarshaller(); - InputStream is = null; - try { - is = new FileInputStream(f); + try (InputStream is = new FileInputStream(f)) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder loader = factory.newDocumentBuilder(); @@ -75,22 +56,18 @@ public class GPXUtils { } if ("http://www.topografix.com/GPX/1/0".equals(namespace)) { Source xmlSource = new javax.xml.transform.dom.DOMSource(document); - Source xsltSource = new StreamSource(Utilities - .loadResourceAsStream("xsl/gpx10to11.xsl")); + Source xsltSource = new StreamSource(Utilities.loadResourceAsStream("xsl/gpx10to11.xsl")); JAXBResult result = new JAXBResult(unmarshaller); TransformerFactory transFact = TransformerFactory.newInstance(); Transformer trans = transFact.newTransformer(xsltSource); trans.transform(xmlSource, result); return (Gpx) result.getResult(); } - throw new JAXBException("Expected GPX 1.0 or GPX1.1 namespace but found \n\"" - + namespace + "\""); + throw new JAXBException("Expected GPX 1.0 or GPX1.1 namespace but found \n\"" + namespace + "\""); } catch (JAXBException e) { throw e; } catch (Exception e) { throw new JAXBException(e); - } finally { - Utilities.closeStream(is); } } @@ -100,19 +77,14 @@ public class GPXUtils { Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); - OutputStream os = null; - try { - os = new FileOutputStream(f); + try (OutputStream os = new FileOutputStream(f)) { marshaller.marshal(gpx, os); - } catch (FileNotFoundException e) { + } catch (IOException e) { throw new JAXBException(e); - } finally { - Utilities.closeStream(os); } } public static void main(String[] args) { - Logging.configureConsoleLogging(); try { loadGpxFile(new File("misc/samples/gpx/gpx11 wpt.gpx")); loadGpxFile(new File("misc/samples/gpx/gpx10 wpt.gpx")); diff --git a/src/main/java/mobac/data/gpx/gpx11/BoundsType.java b/mobac/src/main/java/mobac/data/gpx/gpx11/BoundsType.java similarity index 87% rename from src/main/java/mobac/data/gpx/gpx11/BoundsType.java rename to mobac/src/main/java/mobac/data/gpx/gpx11/BoundsType.java index 0643be5..2029b7d 100644 --- a/src/main/java/mobac/data/gpx/gpx11/BoundsType.java +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/BoundsType.java @@ -1,40 +1,39 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.data.gpx.gpx11; +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlType; + import java.math.BigDecimal; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; - /** - * * Two lat/lon pairs defining the extent of an element. - * - * + * + * *

* Java class for boundsType complex type. - * + * *

* The following schema fragment specifies the expected content contained within * this class. - * + * *

  * <complexType name="boundsType">
  *   <complexContent>
@@ -47,8 +46,6 @@ import javax.xml.bind.annotation.XmlType;
  *   </complexContent>
  * </complexType>
  * 
- * - * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "boundsType") @@ -65,9 +62,8 @@ public class BoundsType { /** * Gets the value of the minlat property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getMinlat() { return minlat; @@ -75,10 +71,9 @@ public class BoundsType { /** * Sets the value of the minlat property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setMinlat(BigDecimal value) { this.minlat = value; @@ -86,9 +81,8 @@ public class BoundsType { /** * Gets the value of the minlon property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getMinlon() { return minlon; @@ -96,10 +90,9 @@ public class BoundsType { /** * Sets the value of the minlon property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setMinlon(BigDecimal value) { this.minlon = value; @@ -107,9 +100,8 @@ public class BoundsType { /** * Gets the value of the maxlat property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getMaxlat() { return maxlat; @@ -117,10 +109,9 @@ public class BoundsType { /** * Sets the value of the maxlat property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setMaxlat(BigDecimal value) { this.maxlat = value; @@ -128,9 +119,8 @@ public class BoundsType { /** * Gets the value of the maxlon property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getMaxlon() { return maxlon; @@ -138,10 +128,9 @@ public class BoundsType { /** * Sets the value of the maxlon property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setMaxlon(BigDecimal value) { this.maxlon = value; diff --git a/mobac/src/main/java/mobac/data/gpx/gpx11/CopyrightType.java b/mobac/src/main/java/mobac/data/gpx/gpx11/CopyrightType.java new file mode 100644 index 0000000..a548ec7 --- /dev/null +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/CopyrightType.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// + +package mobac.data.gpx.gpx11; + +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlSchemaType; +import jakarta.xml.bind.annotation.XmlType; + +import javax.xml.datatype.XMLGregorianCalendar; + +/** + * Information about the copyright holder and any license governing use of this + * file. By linking to an appropriate license, you may place your data into the + * public domain or grant additional usage rights. + * + * + *

+ * Java class for copyrightType complex type. + * + *

+ * The following schema fragment specifies the expected content contained within + * this class. + * + *

+ * <complexType name="copyrightType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="year" type="{http://www.w3.org/2001/XMLSchema}gYear" minOccurs="0"/>
+ *         <element name="license" type="{http://www.w3.org/2001/XMLSchema}anyURI" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="author" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "copyrightType", propOrder = {"year", "license"}) +public class CopyrightType { + + @XmlSchemaType(name = "gYear") + protected XMLGregorianCalendar year; + @XmlSchemaType(name = "anyURI") + protected String license; + @XmlAttribute(required = true) + protected String author; + + /** + * Gets the value of the year property. + * + * @return possible object is {@link XMLGregorianCalendar } + */ + public XMLGregorianCalendar getYear() { + return year; + } + + /** + * Sets the value of the year property. + * + * @param value + * allowed object is {@link XMLGregorianCalendar } + */ + public void setYear(XMLGregorianCalendar value) { + this.year = value; + } + + /** + * Gets the value of the license property. + * + * @return possible object is {@link String } + */ + public String getLicense() { + return license; + } + + /** + * Sets the value of the license property. + * + * @param value + * allowed object is {@link String } + */ + public void setLicense(String value) { + this.license = value; + } + + /** + * Gets the value of the author property. + * + * @return possible object is {@link String } + */ + public String getAuthor() { + return author; + } + + /** + * Sets the value of the author property. + * + * @param value + * allowed object is {@link String } + */ + public void setAuthor(String value) { + this.author = value; + } + +} diff --git a/mobac/src/main/java/mobac/data/gpx/gpx11/EmailType.java b/mobac/src/main/java/mobac/data/gpx/gpx11/EmailType.java new file mode 100644 index 0000000..a6a4beb --- /dev/null +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/EmailType.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// + +package mobac.data.gpx.gpx11; + +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlType; + +/** + * An email address. Broken into two parts (id and domain) to help prevent email + * harvesting. + * + * + *

+ * Java class for emailType complex type. + * + *

+ * The following schema fragment specifies the expected content contained within + * this class. + * + *

+ * <complexType name="emailType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <attribute name="id" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       <attribute name="domain" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "emailType") +public class EmailType { + + @XmlAttribute(required = true) + protected String id; + @XmlAttribute(required = true) + protected String domain; + + /** + * Gets the value of the id property. + * + * @return possible object is {@link String } + */ + public String getId() { + return id; + } + + /** + * Sets the value of the id property. + * + * @param value + * allowed object is {@link String } + */ + public void setId(String value) { + this.id = value; + } + + /** + * Gets the value of the domain property. + * + * @return possible object is {@link String } + */ + public String getDomain() { + return domain; + } + + /** + * Sets the value of the domain property. + * + * @param value + * allowed object is {@link String } + */ + public void setDomain(String value) { + this.domain = value; + } + +} diff --git a/mobac/src/main/java/mobac/data/gpx/gpx11/ExtensionsType.java b/mobac/src/main/java/mobac/data/gpx/gpx11/ExtensionsType.java new file mode 100644 index 0000000..7fb93a4 --- /dev/null +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/ExtensionsType.java @@ -0,0 +1,93 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// + +package mobac.data.gpx.gpx11; + +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlAnyElement; +import jakarta.xml.bind.annotation.XmlType; +import org.w3c.dom.Element; + +import java.util.ArrayList; +import java.util.List; + +/** + * You can add extend GPX by adding your own elements from another schema here. + * + * + *

+ * Java class for extensionsType complex type. + * + *

+ * The following schema fragment specifies the expected content contained within + * this class. + * + *

+ * <complexType name="extensionsType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <any/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "extensionsType", propOrder = {"any"}) +public class ExtensionsType { + + @XmlAnyElement(lax = true) + protected List any; + + /** + * Gets the value of the any property. + * + *

+ * This accessor method returns a reference to the live list, not a snapshot. + * Therefore any modification you make to the returned list will be present + * inside the JAXB object. This is why there is not a set method + * for the any property. + * + *

+ * For example, to add a new item, do as follows: + * + *

+	 * getAny().add(newItem);
+	 * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list {@link Object } + * {@link Element } + */ + public List getAny() { + if (any == null) { + any = new ArrayList(); + } + return this.any; + } + +} diff --git a/src/main/java/mobac/data/gpx/gpx11/Gpx.java b/mobac/src/main/java/mobac/data/gpx/gpx11/Gpx.java similarity index 78% rename from src/main/java/mobac/data/gpx/gpx11/Gpx.java rename to mobac/src/main/java/mobac/data/gpx/gpx11/Gpx.java index 900db04..ff0c13a 100644 --- a/src/main/java/mobac/data/gpx/gpx11/Gpx.java +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/Gpx.java @@ -1,54 +1,51 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ // -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 -// See http://java.sun.com/xml/jaxb -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ // package mobac.data.gpx.gpx11; +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlRootElement; +import jakarta.xml.bind.annotation.XmlType; +import mobac.program.ProgramInfo; + import java.util.ArrayList; import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlType; - -import mobac.program.ProgramInfo; - - /** - * * GPX documents contain a metadata header, followed by waypoints, routes, and * tracks. You can add your own elements to the extensions section of the GPX * document. - * - * + * + * *

* Java class for anonymous complex type. - * + * *

* The following schema fragment specifies the expected content contained within * this class. - * + * *

  * <complexType>
  *   <complexContent>
@@ -66,11 +63,9 @@ import mobac.program.ProgramInfo;
  *   </complexContent>
  * </complexType>
  * 
- * - * */ @XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "", propOrder = { "metadata", "wpt", "rte", "trk", "extensions" }) +@XmlType(name = "", propOrder = {"metadata", "wpt", "rte", "trk", "extensions"}) @XmlRootElement(name = "gpx") public class Gpx { @@ -84,6 +79,9 @@ public class Gpx { @XmlAttribute(required = true) protected String creator; + protected Gpx() { + } + public static Gpx createGpx() { Gpx gpx = new Gpx(); gpx.setVersion("1.1"); @@ -91,14 +89,10 @@ public class Gpx { return gpx; } - protected Gpx() { - } - /** * Gets the value of the metadata property. - * + * * @return possible object is {@link MetadataType } - * */ public MetadataType getMetadata() { return metadata; @@ -106,10 +100,9 @@ public class Gpx { /** * Sets the value of the metadata property. - * + * * @param value * allowed object is {@link MetadataType } - * */ public void setMetadata(MetadataType value) { this.metadata = value; @@ -117,25 +110,23 @@ public class Gpx { /** * Gets the value of the wpt property. - * + * *

- * This accessor method returns a reference to the live list, not a - * snapshot. Therefore any modification you make to the returned list will - * be present inside the JAXB object. This is why there is not a - * set method for the wpt property. - * + * This accessor method returns a reference to the live list, not a snapshot. + * Therefore any modification you make to the returned list will be present + * inside the JAXB object. This is why there is not a set method + * for the wpt property. + * *

* For example, to add a new item, do as follows: - * + * *

 	 * getWpt().add(newItem);
 	 * 
- * - * + * + * *

* Objects of the following type(s) are allowed in the list {@link WptType } - * - * */ public List getWpt() { if (wpt == null) { @@ -146,25 +137,23 @@ public class Gpx { /** * Gets the value of the rte property. - * + * *

- * This accessor method returns a reference to the live list, not a - * snapshot. Therefore any modification you make to the returned list will - * be present inside the JAXB object. This is why there is not a - * set method for the rte property. - * + * This accessor method returns a reference to the live list, not a snapshot. + * Therefore any modification you make to the returned list will be present + * inside the JAXB object. This is why there is not a set method + * for the rte property. + * *

* For example, to add a new item, do as follows: - * + * *

 	 * getRte().add(newItem);
 	 * 
- * - * + * + * *

* Objects of the following type(s) are allowed in the list {@link RteType } - * - * */ public List getRte() { if (rte == null) { @@ -175,25 +164,23 @@ public class Gpx { /** * Gets the value of the trk property. - * + * *

- * This accessor method returns a reference to the live list, not a - * snapshot. Therefore any modification you make to the returned list will - * be present inside the JAXB object. This is why there is not a - * set method for the trk property. - * + * This accessor method returns a reference to the live list, not a snapshot. + * Therefore any modification you make to the returned list will be present + * inside the JAXB object. This is why there is not a set method + * for the trk property. + * *

* For example, to add a new item, do as follows: - * + * *

 	 * getTrk().add(newItem);
 	 * 
- * - * + * + * *

* Objects of the following type(s) are allowed in the list {@link TrkType } - * - * */ public List getTrk() { if (trk == null) { @@ -204,9 +191,8 @@ public class Gpx { /** * Gets the value of the extensions property. - * + * * @return possible object is {@link ExtensionsType } - * */ public ExtensionsType getExtensions() { return extensions; @@ -214,10 +200,9 @@ public class Gpx { /** * Sets the value of the extensions property. - * + * * @param value * allowed object is {@link ExtensionsType } - * */ public void setExtensions(ExtensionsType value) { this.extensions = value; @@ -225,9 +210,8 @@ public class Gpx { /** * Gets the value of the version property. - * + * * @return possible object is {@link String } - * */ public String getVersion() { if (version == null) { @@ -239,10 +223,9 @@ public class Gpx { /** * Sets the value of the version property. - * + * * @param value * allowed object is {@link String } - * */ public void setVersion(String value) { this.version = value; @@ -250,9 +233,8 @@ public class Gpx { /** * Gets the value of the creator property. - * + * * @return possible object is {@link String } - * */ public String getCreator() { return creator; @@ -260,10 +242,9 @@ public class Gpx { /** * Sets the value of the creator property. - * + * * @param value * allowed object is {@link String } - * */ public void setCreator(String value) { this.creator = value; diff --git a/mobac/src/main/java/mobac/data/gpx/gpx11/LinkType.java b/mobac/src/main/java/mobac/data/gpx/gpx11/LinkType.java new file mode 100644 index 0000000..6ca0509 --- /dev/null +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/LinkType.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// + +package mobac.data.gpx.gpx11; + +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlSchemaType; +import jakarta.xml.bind.annotation.XmlType; + +/** + * A link to an external resource (Web page, digital photo, video clip, etc) + * with additional information. + * + * + *

+ * Java class for linkType complex type. + * + *

+ * The following schema fragment specifies the expected content contained within + * this class. + * + *

+ * <complexType name="linkType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="text" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="type" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *       </sequence>
+ *       <attribute name="href" use="required" type="{http://www.w3.org/2001/XMLSchema}anyURI" />
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "linkType", propOrder = {"text", "type"}) +public class LinkType { + + protected String text; + protected String type; + @XmlAttribute(required = true) + @XmlSchemaType(name = "anyURI") + protected String href; + + /** + * Gets the value of the text property. + * + * @return possible object is {@link String } + */ + public String getText() { + return text; + } + + /** + * Sets the value of the text property. + * + * @param value + * allowed object is {@link String } + */ + public void setText(String value) { + this.text = value; + } + + /** + * Gets the value of the type property. + * + * @return possible object is {@link String } + */ + public String getType() { + return type; + } + + /** + * Sets the value of the type property. + * + * @param value + * allowed object is {@link String } + */ + public void setType(String value) { + this.type = value; + } + + /** + * Gets the value of the href property. + * + * @return possible object is {@link String } + */ + public String getHref() { + return href; + } + + /** + * Sets the value of the href property. + * + * @param value + * allowed object is {@link String } + */ + public void setHref(String value) { + this.href = value; + } + +} diff --git a/mobac/src/main/java/mobac/data/gpx/gpx11/MetadataType.java b/mobac/src/main/java/mobac/data/gpx/gpx11/MetadataType.java new file mode 100644 index 0000000..97b7fb0 --- /dev/null +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/MetadataType.java @@ -0,0 +1,261 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// + +package mobac.data.gpx.gpx11; + +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlType; + +import javax.xml.datatype.XMLGregorianCalendar; +import java.util.ArrayList; +import java.util.List; + +/** + * Information about the GPX file, author, and copyright restrictions goes in + * the metadata section. Providing rich, meaningful information about your GPX + * files allows others to search for and use your GPS data. + * + * + *

+ * Java class for metadataType complex type. + * + *

+ * The following schema fragment specifies the expected content contained within + * this class. + * + *

+ * <complexType name="metadataType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="desc" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="author" type="{http://www.topografix.com/GPX/1/1}personType" minOccurs="0"/>
+ *         <element name="copyright" type="{http://www.topografix.com/GPX/1/1}copyrightType" minOccurs="0"/>
+ *         <element name="link" type="{http://www.topografix.com/GPX/1/1}linkType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="time" type="{http://www.w3.org/2001/XMLSchema}dateTime" minOccurs="0"/>
+ *         <element name="keywords" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="bounds" type="{http://www.topografix.com/GPX/1/1}boundsType" minOccurs="0"/>
+ *         <element name="extensions" type="{http://www.topografix.com/GPX/1/1}extensionsType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "metadataType", propOrder = {"name", "desc", "author", "copyright", "link", "time", "keywords", + "bounds", "extensions"}) +public class MetadataType { + + protected String name; + protected String desc; + protected PersonType author; + protected CopyrightType copyright; + protected List link; + protected XMLGregorianCalendar time; + protected String keywords; + protected BoundsType bounds; + protected ExtensionsType extensions; + + /** + * Gets the value of the name property. + * + * @return possible object is {@link String } + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is {@link String } + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the desc property. + * + * @return possible object is {@link String } + */ + public String getDesc() { + return desc; + } + + /** + * Sets the value of the desc property. + * + * @param value + * allowed object is {@link String } + */ + public void setDesc(String value) { + this.desc = value; + } + + /** + * Gets the value of the author property. + * + * @return possible object is {@link PersonType } + */ + public PersonType getAuthor() { + return author; + } + + /** + * Sets the value of the author property. + * + * @param value + * allowed object is {@link PersonType } + */ + public void setAuthor(PersonType value) { + this.author = value; + } + + /** + * Gets the value of the copyright property. + * + * @return possible object is {@link CopyrightType } + */ + public CopyrightType getCopyright() { + return copyright; + } + + /** + * Sets the value of the copyright property. + * + * @param value + * allowed object is {@link CopyrightType } + */ + public void setCopyright(CopyrightType value) { + this.copyright = value; + } + + /** + * Gets the value of the link property. + * + *

+ * This accessor method returns a reference to the live list, not a snapshot. + * Therefore any modification you make to the returned list will be present + * inside the JAXB object. This is why there is not a set method + * for the link property. + * + *

+ * For example, to add a new item, do as follows: + * + *

+	 * getLink().add(newItem);
+	 * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list {@link LinkType } + */ + public List getLink() { + if (link == null) { + link = new ArrayList(); + } + return this.link; + } + + /** + * Gets the value of the time property. + * + * @return possible object is {@link XMLGregorianCalendar } + */ + public XMLGregorianCalendar getTime() { + return time; + } + + /** + * Sets the value of the time property. + * + * @param value + * allowed object is {@link XMLGregorianCalendar } + */ + public void setTime(XMLGregorianCalendar value) { + this.time = value; + } + + /** + * Gets the value of the keywords property. + * + * @return possible object is {@link String } + */ + public String getKeywords() { + return keywords; + } + + /** + * Sets the value of the keywords property. + * + * @param value + * allowed object is {@link String } + */ + public void setKeywords(String value) { + this.keywords = value; + } + + /** + * Gets the value of the bounds property. + * + * @return possible object is {@link BoundsType } + */ + public BoundsType getBounds() { + return bounds; + } + + /** + * Sets the value of the bounds property. + * + * @param value + * allowed object is {@link BoundsType } + */ + public void setBounds(BoundsType value) { + this.bounds = value; + } + + /** + * Gets the value of the extensions property. + * + * @return possible object is {@link ExtensionsType } + */ + public ExtensionsType getExtensions() { + return extensions; + } + + /** + * Sets the value of the extensions property. + * + * @param value + * allowed object is {@link ExtensionsType } + */ + public void setExtensions(ExtensionsType value) { + this.extensions = value; + } + +} diff --git a/mobac/src/main/java/mobac/data/gpx/gpx11/PersonType.java b/mobac/src/main/java/mobac/data/gpx/gpx11/PersonType.java new file mode 100644 index 0000000..abe66ee --- /dev/null +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/PersonType.java @@ -0,0 +1,120 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// + +package mobac.data.gpx.gpx11; + +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlType; + +/** + * A person or organization. + * + * + *

+ * Java class for personType complex type. + * + *

+ * The following schema fragment specifies the expected content contained within + * this class. + * + *

+ * <complexType name="personType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="email" type="{http://www.topografix.com/GPX/1/1}emailType" minOccurs="0"/>
+ *         <element name="link" type="{http://www.topografix.com/GPX/1/1}linkType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "personType", propOrder = {"name", "email", "link"}) +public class PersonType { + + protected String name; + protected EmailType email; + protected LinkType link; + + /** + * Gets the value of the name property. + * + * @return possible object is {@link String } + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is {@link String } + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the email property. + * + * @return possible object is {@link EmailType } + */ + public EmailType getEmail() { + return email; + } + + /** + * Sets the value of the email property. + * + * @param value + * allowed object is {@link EmailType } + */ + public void setEmail(EmailType value) { + this.email = value; + } + + /** + * Gets the value of the link property. + * + * @return possible object is {@link LinkType } + */ + public LinkType getLink() { + return link; + } + + /** + * Sets the value of the link property. + * + * @param value + * allowed object is {@link LinkType } + */ + public void setLink(LinkType value) { + this.link = value; + } + +} diff --git a/src/main/java/mobac/data/gpx/gpx11/PtType.java b/mobac/src/main/java/mobac/data/gpx/gpx11/PtType.java similarity index 83% rename from src/main/java/mobac/data/gpx/gpx11/PtType.java rename to mobac/src/main/java/mobac/data/gpx/gpx11/PtType.java index 2f27b36..897371a 100644 --- a/src/main/java/mobac/data/gpx/gpx11/PtType.java +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/PtType.java @@ -1,51 +1,49 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ // -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 -// See http://java.sun.com/xml/jaxb -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ // package mobac.data.gpx.gpx11; -import java.math.BigDecimal; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlType; -import javax.xml.datatype.XMLGregorianCalendar; - +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlType; import mobac.data.gpx.interfaces.GpxPoint; +import javax.xml.datatype.XMLGregorianCalendar; +import java.math.BigDecimal; + /** - * * A geographic point with optional elevation and time. Available for use by * other schemas. - * - * + * + * *

* Java class for ptType complex type. - * + * *

* The following schema fragment specifies the expected content contained within * this class. - * + * *

  * <complexType name="ptType">
  *   <complexContent>
@@ -60,11 +58,9 @@ import mobac.data.gpx.interfaces.GpxPoint;
  *   </complexContent>
  * </complexType>
  * 
- * - * */ @XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "ptType", propOrder = { "ele", "time" }) +@XmlType(name = "ptType", propOrder = {"ele", "time"}) public class PtType implements GpxPoint { protected BigDecimal ele; @@ -76,9 +72,8 @@ public class PtType implements GpxPoint { /** * Gets the value of the ele property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getEle() { return ele; @@ -86,10 +81,9 @@ public class PtType implements GpxPoint { /** * Sets the value of the ele property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setEle(BigDecimal value) { this.ele = value; @@ -97,9 +91,8 @@ public class PtType implements GpxPoint { /** * Gets the value of the time property. - * + * * @return possible object is {@link XMLGregorianCalendar } - * */ public XMLGregorianCalendar getTime() { return time; @@ -107,10 +100,9 @@ public class PtType implements GpxPoint { /** * Sets the value of the time property. - * + * * @param value * allowed object is {@link XMLGregorianCalendar } - * */ public void setTime(XMLGregorianCalendar value) { this.time = value; @@ -118,9 +110,8 @@ public class PtType implements GpxPoint { /** * Gets the value of the lat property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getLat() { return lat; @@ -128,10 +119,9 @@ public class PtType implements GpxPoint { /** * Sets the value of the lat property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setLat(BigDecimal value) { this.lat = value; @@ -139,9 +129,8 @@ public class PtType implements GpxPoint { /** * Gets the value of the lon property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getLon() { return lon; @@ -149,10 +138,9 @@ public class PtType implements GpxPoint { /** * Sets the value of the lon property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setLon(BigDecimal value) { this.lon = value; diff --git a/mobac/src/main/java/mobac/data/gpx/gpx11/PtsegType.java b/mobac/src/main/java/mobac/data/gpx/gpx11/PtsegType.java new file mode 100644 index 0000000..3b3d353 --- /dev/null +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/PtsegType.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// + +package mobac.data.gpx.gpx11; + +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlType; + +import java.util.ArrayList; +import java.util.List; + +/** + * An ordered sequence of points. (for polygons or polylines, e.g.) + * + * + *

+ * Java class for ptsegType complex type. + * + *

+ * The following schema fragment specifies the expected content contained within + * this class. + * + *

+ * <complexType name="ptsegType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="pt" type="{http://www.topografix.com/GPX/1/1}ptType" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ptsegType", propOrder = {"pt"}) +public class PtsegType { + + protected List pt; + + /** + * Gets the value of the pt property. + * + *

+ * This accessor method returns a reference to the live list, not a snapshot. + * Therefore any modification you make to the returned list will be present + * inside the JAXB object. This is why there is not a set method + * for the pt property. + * + *

+ * For example, to add a new item, do as follows: + * + *

+	 * getPt().add(newItem);
+	 * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list {@link PtType } + */ + public List getPt() { + if (pt == null) { + pt = new ArrayList(); + } + return this.pt; + } + +} diff --git a/mobac/src/main/java/mobac/data/gpx/gpx11/RteType.java b/mobac/src/main/java/mobac/data/gpx/gpx11/RteType.java new file mode 100644 index 0000000..9e7482e --- /dev/null +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/RteType.java @@ -0,0 +1,269 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// + +package mobac.data.gpx.gpx11; + +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlSchemaType; +import jakarta.xml.bind.annotation.XmlType; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +/** + * rte represents route - an ordered list of waypoints representing a series of + * turn points leading to a destination. + * + * + *

+ * Java class for rteType complex type. + * + *

+ * The following schema fragment specifies the expected content contained within + * this class. + * + *

+ * <complexType name="rteType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="cmt" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="desc" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="src" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="link" type="{http://www.topografix.com/GPX/1/1}linkType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="number" type="{http://www.w3.org/2001/XMLSchema}nonNegativeInteger" minOccurs="0"/>
+ *         <element name="type" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="extensions" type="{http://www.topografix.com/GPX/1/1}extensionsType" minOccurs="0"/>
+ *         <element name="rtept" type="{http://www.topografix.com/GPX/1/1}wptType" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "rteType", propOrder = {"name", "cmt", "desc", "src", "link", "number", "type", "extensions", "rtept"}) +public class RteType { + + protected String name; + protected String cmt; + protected String desc; + protected String src; + protected List link; + @XmlSchemaType(name = "nonNegativeInteger") + protected BigInteger number; + protected String type; + protected ExtensionsType extensions; + protected List rtept; + + /** + * Gets the value of the name property. + * + * @return possible object is {@link String } + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is {@link String } + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the cmt property. + * + * @return possible object is {@link String } + */ + public String getCmt() { + return cmt; + } + + /** + * Sets the value of the cmt property. + * + * @param value + * allowed object is {@link String } + */ + public void setCmt(String value) { + this.cmt = value; + } + + /** + * Gets the value of the desc property. + * + * @return possible object is {@link String } + */ + public String getDesc() { + return desc; + } + + /** + * Sets the value of the desc property. + * + * @param value + * allowed object is {@link String } + */ + public void setDesc(String value) { + this.desc = value; + } + + /** + * Gets the value of the src property. + * + * @return possible object is {@link String } + */ + public String getSrc() { + return src; + } + + /** + * Sets the value of the src property. + * + * @param value + * allowed object is {@link String } + */ + public void setSrc(String value) { + this.src = value; + } + + /** + * Gets the value of the link property. + * + *

+ * This accessor method returns a reference to the live list, not a snapshot. + * Therefore any modification you make to the returned list will be present + * inside the JAXB object. This is why there is not a set method + * for the link property. + * + *

+ * For example, to add a new item, do as follows: + * + *

+	 * getLink().add(newItem);
+	 * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list {@link LinkType } + */ + public List getLink() { + if (link == null) { + link = new ArrayList(); + } + return this.link; + } + + /** + * Gets the value of the number property. + * + * @return possible object is {@link BigInteger } + */ + public BigInteger getNumber() { + return number; + } + + /** + * Sets the value of the number property. + * + * @param value + * allowed object is {@link BigInteger } + */ + public void setNumber(BigInteger value) { + this.number = value; + } + + /** + * Gets the value of the type property. + * + * @return possible object is {@link String } + */ + public String getType() { + return type; + } + + /** + * Sets the value of the type property. + * + * @param value + * allowed object is {@link String } + */ + public void setType(String value) { + this.type = value; + } + + /** + * Gets the value of the extensions property. + * + * @return possible object is {@link ExtensionsType } + */ + public ExtensionsType getExtensions() { + return extensions; + } + + /** + * Sets the value of the extensions property. + * + * @param value + * allowed object is {@link ExtensionsType } + */ + public void setExtensions(ExtensionsType value) { + this.extensions = value; + } + + /** + * Gets the value of the rtept property. + * + *

+ * This accessor method returns a reference to the live list, not a snapshot. + * Therefore any modification you make to the returned list will be present + * inside the JAXB object. This is why there is not a set method + * for the rtept property. + * + *

+ * For example, to add a new item, do as follows: + * + *

+	 * getRtept().add(newItem);
+	 * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list {@link WptType } + */ + public List getRtept() { + if (rtept == null) { + rtept = new ArrayList(); + } + return this.rtept; + } + +} diff --git a/mobac/src/main/java/mobac/data/gpx/gpx11/TrkType.java b/mobac/src/main/java/mobac/data/gpx/gpx11/TrkType.java new file mode 100644 index 0000000..0e52ed7 --- /dev/null +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/TrkType.java @@ -0,0 +1,268 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// + +package mobac.data.gpx.gpx11; + +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlSchemaType; +import jakarta.xml.bind.annotation.XmlType; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +/** + * trk represents a track - an ordered list of points describing a path. + * + * + *

+ * Java class for trkType complex type. + * + *

+ * The following schema fragment specifies the expected content contained within + * this class. + * + *

+ * <complexType name="trkType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="cmt" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="desc" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="src" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="link" type="{http://www.topografix.com/GPX/1/1}linkType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="number" type="{http://www.w3.org/2001/XMLSchema}nonNegativeInteger" minOccurs="0"/>
+ *         <element name="type" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="extensions" type="{http://www.topografix.com/GPX/1/1}extensionsType" minOccurs="0"/>
+ *         <element name="trkseg" type="{http://www.topografix.com/GPX/1/1}trksegType" maxOccurs="unbounded" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "trkType", propOrder = {"name", "cmt", "desc", "src", "link", "number", "type", "extensions", "trkseg"}) +public class TrkType { + + protected String name; + protected String cmt; + protected String desc; + protected String src; + protected List link; + @XmlSchemaType(name = "nonNegativeInteger") + protected BigInteger number; + protected String type; + protected ExtensionsType extensions; + protected List trkseg; + + /** + * Gets the value of the name property. + * + * @return possible object is {@link String } + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is {@link String } + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the cmt property. + * + * @return possible object is {@link String } + */ + public String getCmt() { + return cmt; + } + + /** + * Sets the value of the cmt property. + * + * @param value + * allowed object is {@link String } + */ + public void setCmt(String value) { + this.cmt = value; + } + + /** + * Gets the value of the desc property. + * + * @return possible object is {@link String } + */ + public String getDesc() { + return desc; + } + + /** + * Sets the value of the desc property. + * + * @param value + * allowed object is {@link String } + */ + public void setDesc(String value) { + this.desc = value; + } + + /** + * Gets the value of the src property. + * + * @return possible object is {@link String } + */ + public String getSrc() { + return src; + } + + /** + * Sets the value of the src property. + * + * @param value + * allowed object is {@link String } + */ + public void setSrc(String value) { + this.src = value; + } + + /** + * Gets the value of the link property. + * + *

+ * This accessor method returns a reference to the live list, not a snapshot. + * Therefore any modification you make to the returned list will be present + * inside the JAXB object. This is why there is not a set method + * for the link property. + * + *

+ * For example, to add a new item, do as follows: + * + *

+	 * getLink().add(newItem);
+	 * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list {@link LinkType } + */ + public List getLink() { + if (link == null) { + link = new ArrayList(); + } + return this.link; + } + + /** + * Gets the value of the number property. + * + * @return possible object is {@link BigInteger } + */ + public BigInteger getNumber() { + return number; + } + + /** + * Sets the value of the number property. + * + * @param value + * allowed object is {@link BigInteger } + */ + public void setNumber(BigInteger value) { + this.number = value; + } + + /** + * Gets the value of the type property. + * + * @return possible object is {@link String } + */ + public String getType() { + return type; + } + + /** + * Sets the value of the type property. + * + * @param value + * allowed object is {@link String } + */ + public void setType(String value) { + this.type = value; + } + + /** + * Gets the value of the extensions property. + * + * @return possible object is {@link ExtensionsType } + */ + public ExtensionsType getExtensions() { + return extensions; + } + + /** + * Sets the value of the extensions property. + * + * @param value + * allowed object is {@link ExtensionsType } + */ + public void setExtensions(ExtensionsType value) { + this.extensions = value; + } + + /** + * Gets the value of the trkseg property. + * + *

+ * This accessor method returns a reference to the live list, not a snapshot. + * Therefore any modification you make to the returned list will be present + * inside the JAXB object. This is why there is not a set method + * for the trkseg property. + * + *

+ * For example, to add a new item, do as follows: + * + *

+	 * getTrkseg().add(newItem);
+	 * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list {@link TrksegType } + */ + public List getTrkseg() { + if (trkseg == null) { + trkseg = new ArrayList(); + } + return this.trkseg; + } + +} diff --git a/mobac/src/main/java/mobac/data/gpx/gpx11/TrksegType.java b/mobac/src/main/java/mobac/data/gpx/gpx11/TrksegType.java new file mode 100644 index 0000000..002fccc --- /dev/null +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/TrksegType.java @@ -0,0 +1,113 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// + +package mobac.data.gpx.gpx11; + +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlType; + +import java.util.ArrayList; +import java.util.List; + +/** + * A Track Segment holds a list of Track Points which are logically connected in + * order. To represent a single GPS track where GPS reception was lost, or the + * GPS receiver was turned off, start a new Track Segment for each continuous + * span of track data. + * + * + *

+ * Java class for trksegType complex type. + * + *

+ * The following schema fragment specifies the expected content contained within + * this class. + * + *

+ * <complexType name="trksegType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="trkpt" type="{http://www.topografix.com/GPX/1/1}wptType" maxOccurs="unbounded" minOccurs="0"/>
+ *         <element name="extensions" type="{http://www.topografix.com/GPX/1/1}extensionsType" minOccurs="0"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "trksegType", propOrder = {"trkpt", "extensions"}) +public class TrksegType { + + protected List trkpt; + protected ExtensionsType extensions; + + /** + * Gets the value of the trkpt property. + * + *

+ * This accessor method returns a reference to the live list, not a snapshot. + * Therefore any modification you make to the returned list will be present + * inside the JAXB object. This is why there is not a set method + * for the trkpt property. + * + *

+ * For example, to add a new item, do as follows: + * + *

+	 * getTrkpt().add(newItem);
+	 * 
+ * + * + *

+ * Objects of the following type(s) are allowed in the list {@link WptType } + */ + public List getTrkpt() { + if (trkpt == null) { + trkpt = new ArrayList(); + } + return this.trkpt; + } + + /** + * Gets the value of the extensions property. + * + * @return possible object is {@link ExtensionsType } + */ + public ExtensionsType getExtensions() { + return extensions; + } + + /** + * Sets the value of the extensions property. + * + * @param value + * allowed object is {@link ExtensionsType } + */ + public void setExtensions(ExtensionsType value) { + this.extensions = value; + } + +} diff --git a/src/main/java/mobac/data/gpx/gpx11/WptType.java b/mobac/src/main/java/mobac/data/gpx/gpx11/WptType.java similarity index 86% rename from src/main/java/mobac/data/gpx/gpx11/WptType.java rename to mobac/src/main/java/mobac/data/gpx/gpx11/WptType.java index 8ed9f07..cc3b83b 100644 --- a/src/main/java/mobac/data/gpx/gpx11/WptType.java +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/WptType.java @@ -1,54 +1,52 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ // -// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 -// See http://java.sun.com/xml/jaxb -// Any modifications to this file will be lost upon recompilation of the source schema. -// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ // package mobac.data.gpx.gpx11; +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlSchemaType; +import jakarta.xml.bind.annotation.XmlType; +import mobac.data.gpx.interfaces.GpxPoint; + +import javax.xml.datatype.XMLGregorianCalendar; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlSchemaType; -import javax.xml.bind.annotation.XmlType; -import javax.xml.datatype.XMLGregorianCalendar; - -import mobac.data.gpx.interfaces.GpxPoint; - /** - * * wpt represents a waypoint, point of interest, or named feature on a map. - * - * + * + * *

* Java class for wptType complex type. - * + * *

* The following schema fragment specifies the expected content contained within * this class. - * + * *

  * <complexType name="wptType">
  *   <complexContent>
@@ -80,13 +78,10 @@ import mobac.data.gpx.interfaces.GpxPoint;
  *   </complexContent>
  * </complexType>
  * 
- * - * */ @XmlAccessorType(XmlAccessType.FIELD) -@XmlType(name = "wptType", propOrder = { "ele", "time", "magvar", "geoidheight", "name", "cmt", - "desc", "src", "link", "sym", "type", "fix", "sat", "hdop", "vdop", "pdop", - "ageofdgpsdata", "dgpsid", "extensions" }) +@XmlType(name = "wptType", propOrder = {"ele", "time", "magvar", "geoidheight", "name", "cmt", "desc", "src", "link", + "sym", "type", "fix", "sat", "hdop", "vdop", "pdop", "ageofdgpsdata", "dgpsid", "extensions"}) public class WptType implements GpxPoint { protected BigDecimal ele; @@ -116,9 +111,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the ele property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getEle() { return ele; @@ -126,10 +120,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the ele property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setEle(BigDecimal value) { this.ele = value; @@ -137,9 +130,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the time property. - * + * * @return possible object is {@link XMLGregorianCalendar } - * */ public XMLGregorianCalendar getTime() { return time; @@ -147,10 +139,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the time property. - * + * * @param value * allowed object is {@link XMLGregorianCalendar } - * */ public void setTime(XMLGregorianCalendar value) { this.time = value; @@ -158,9 +149,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the magvar property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getMagvar() { return magvar; @@ -168,10 +158,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the magvar property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setMagvar(BigDecimal value) { this.magvar = value; @@ -179,9 +168,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the geoidheight property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getGeoidheight() { return geoidheight; @@ -189,10 +177,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the geoidheight property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setGeoidheight(BigDecimal value) { this.geoidheight = value; @@ -200,9 +187,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the name property. - * + * * @return possible object is {@link String } - * */ public String getName() { return name; @@ -210,10 +196,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the name property. - * + * * @param value * allowed object is {@link String } - * */ public void setName(String value) { this.name = value; @@ -221,9 +206,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the cmt property. - * + * * @return possible object is {@link String } - * */ public String getCmt() { return cmt; @@ -231,10 +215,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the cmt property. - * + * * @param value * allowed object is {@link String } - * */ public void setCmt(String value) { this.cmt = value; @@ -242,9 +225,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the desc property. - * + * * @return possible object is {@link String } - * */ public String getDesc() { return desc; @@ -252,10 +234,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the desc property. - * + * * @param value * allowed object is {@link String } - * */ public void setDesc(String value) { this.desc = value; @@ -263,9 +244,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the src property. - * + * * @return possible object is {@link String } - * */ public String getSrc() { return src; @@ -273,10 +253,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the src property. - * + * * @param value * allowed object is {@link String } - * */ public void setSrc(String value) { this.src = value; @@ -284,25 +263,23 @@ public class WptType implements GpxPoint { /** * Gets the value of the link property. - * + * *

- * This accessor method returns a reference to the live list, not a - * snapshot. Therefore any modification you make to the returned list will - * be present inside the JAXB object. This is why there is not a - * set method for the link property. - * + * This accessor method returns a reference to the live list, not a snapshot. + * Therefore any modification you make to the returned list will be present + * inside the JAXB object. This is why there is not a set method + * for the link property. + * *

* For example, to add a new item, do as follows: - * + * *

 	 * getLink().add(newItem);
 	 * 
- * - * + * + * *

* Objects of the following type(s) are allowed in the list {@link LinkType } - * - * */ public List getLink() { if (link == null) { @@ -313,9 +290,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the sym property. - * + * * @return possible object is {@link String } - * */ public String getSym() { return sym; @@ -323,10 +299,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the sym property. - * + * * @param value * allowed object is {@link String } - * */ public void setSym(String value) { this.sym = value; @@ -334,9 +309,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the type property. - * + * * @return possible object is {@link String } - * */ public String getType() { return type; @@ -344,10 +318,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the type property. - * + * * @param value * allowed object is {@link String } - * */ public void setType(String value) { this.type = value; @@ -355,9 +328,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the fix property. - * + * * @return possible object is {@link String } - * */ public String getFix() { return fix; @@ -365,10 +337,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the fix property. - * + * * @param value * allowed object is {@link String } - * */ public void setFix(String value) { this.fix = value; @@ -376,9 +347,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the sat property. - * + * * @return possible object is {@link BigInteger } - * */ public BigInteger getSat() { return sat; @@ -386,10 +356,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the sat property. - * + * * @param value * allowed object is {@link BigInteger } - * */ public void setSat(BigInteger value) { this.sat = value; @@ -397,9 +366,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the hdop property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getHdop() { return hdop; @@ -407,10 +375,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the hdop property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setHdop(BigDecimal value) { this.hdop = value; @@ -418,9 +385,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the vdop property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getVdop() { return vdop; @@ -428,10 +394,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the vdop property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setVdop(BigDecimal value) { this.vdop = value; @@ -439,9 +404,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the pdop property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getPdop() { return pdop; @@ -449,10 +413,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the pdop property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setPdop(BigDecimal value) { this.pdop = value; @@ -460,9 +423,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the ageofdgpsdata property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getAgeofdgpsdata() { return ageofdgpsdata; @@ -470,10 +432,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the ageofdgpsdata property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setAgeofdgpsdata(BigDecimal value) { this.ageofdgpsdata = value; @@ -481,9 +442,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the dgpsid property. - * + * * @return possible object is {@link Integer } - * */ public Integer getDgpsid() { return dgpsid; @@ -491,10 +451,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the dgpsid property. - * + * * @param value * allowed object is {@link Integer } - * */ public void setDgpsid(Integer value) { this.dgpsid = value; @@ -502,9 +461,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the extensions property. - * + * * @return possible object is {@link ExtensionsType } - * */ public ExtensionsType getExtensions() { return extensions; @@ -512,10 +470,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the extensions property. - * + * * @param value * allowed object is {@link ExtensionsType } - * */ public void setExtensions(ExtensionsType value) { this.extensions = value; @@ -523,9 +480,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the lat property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getLat() { return lat; @@ -533,10 +489,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the lat property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setLat(BigDecimal value) { this.lat = value; @@ -544,9 +499,8 @@ public class WptType implements GpxPoint { /** * Gets the value of the lon property. - * + * * @return possible object is {@link BigDecimal } - * */ public BigDecimal getLon() { return lon; @@ -554,10 +508,9 @@ public class WptType implements GpxPoint { /** * Sets the value of the lon property. - * + * * @param value * allowed object is {@link BigDecimal } - * */ public void setLon(BigDecimal value) { this.lon = value; diff --git a/mobac/src/main/java/mobac/data/gpx/gpx11/package-info.java b/mobac/src/main/java/mobac/data/gpx/gpx11/package-info.java new file mode 100644 index 0000000..583f0b8 --- /dev/null +++ b/mobac/src/main/java/mobac/data/gpx/gpx11/package-info.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 2 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + ******************************************************************************/ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) +// Reference Implementation, vJAXB 2.1.3 in JDK 1.6 +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source +// schema. +// Generated on: 2009.08.04 at 03:45:03 PM MESZ +// + +@jakarta.xml.bind.annotation.XmlSchema(namespace = "http://www.topografix.com/GPX/1/1", elementFormDefault = jakarta.xml.bind.annotation.XmlNsForm.QUALIFIED) +@XmlJavaTypeAdapters({@XmlJavaTypeAdapter(value = BigDecimalAdapter.class, type = BigDecimal.class)}) +package mobac.data.gpx.gpx11; + +import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapters; +import mobac.program.jaxb.BigDecimalAdapter; + +import java.math.BigDecimal; diff --git a/src/main/java/mobac/data/gpx/interfaces/GpxPoint.java b/mobac/src/main/java/mobac/data/gpx/interfaces/GpxPoint.java similarity index 81% rename from src/main/java/mobac/data/gpx/interfaces/GpxPoint.java rename to mobac/src/main/java/mobac/data/gpx/interfaces/GpxPoint.java index b1b65b8..e77d52c 100644 --- a/src/main/java/mobac/data/gpx/interfaces/GpxPoint.java +++ b/mobac/src/main/java/mobac/data/gpx/interfaces/GpxPoint.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.data.gpx.interfaces; @@ -20,9 +20,9 @@ import java.math.BigDecimal; public interface GpxPoint { - public BigDecimal getLat(); + BigDecimal getLat(); - public BigDecimal getLon(); + BigDecimal getLon(); - public BigDecimal getEle(); + BigDecimal getEle(); } diff --git a/mobac/src/main/java/mobac/exceptions/AbortedByUserException.java b/mobac/src/main/java/mobac/exceptions/AbortedByUserException.java new file mode 100644 index 0000000..05f8cfe --- /dev/null +++ b/mobac/src/main/java/mobac/exceptions/AbortedByUserException.java @@ -0,0 +1,23 @@ +package mobac.exceptions; + +import java.io.PrintStream; +import java.io.PrintWriter; + +public class AbortedByUserException extends RuntimeException { + + public AbortedByUserException() { + } + + @Override + public StackTraceElement[] getStackTrace() { + return new StackTraceElement[0]; + } + + @Override + public void printStackTrace(PrintStream s) { + } + + @Override + public void printStackTrace(PrintWriter s) { + } +} diff --git a/src/main/java/mobac/exceptions/AtlasTestException.java b/mobac/src/main/java/mobac/exceptions/AtlasTestException.java similarity index 88% rename from src/main/java/mobac/exceptions/AtlasTestException.java rename to mobac/src/main/java/mobac/exceptions/AtlasTestException.java index bc148b3..d8a93f6 100644 --- a/src/main/java/mobac/exceptions/AtlasTestException.java +++ b/mobac/src/main/java/mobac/exceptions/AtlasTestException.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.exceptions; @@ -22,8 +22,8 @@ import mobac.program.interfaces.MapInterface; public class AtlasTestException extends Exception { public AtlasTestException(String message, MapInterface map) { - super(message + "\nError caused by map \"" + map.getName() + "\" on layer \"" - + map.getLayer().getName() + "\""); + super(message + "\nError caused by map \"" + map.getName() + "\" on layer \"" + map.getLayer().getName() + + "\""); } public AtlasTestException(String message, LayerInterface layer) { diff --git a/mobac/src/main/java/mobac/exceptions/DownloadFailedException.java b/mobac/src/main/java/mobac/exceptions/DownloadFailedException.java new file mode 100644 index 0000000..115e479 --- /dev/null +++ b/mobac/src/main/java/mobac/exceptions/DownloadFailedException.java @@ -0,0 +1,121 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.exceptions; + +import mobac.utilities.HtmlStrip; +import mobac.utilities.imageio.ImageFormatDetector; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class DownloadFailedException extends IOException { + + private static final Logger log = LoggerFactory.getLogger(DownloadFailedException.class); + + private static final Pattern CHARSET = Pattern.compile("charset=([a-zA-Z0-9_\\-]+)", Pattern.CASE_INSENSITIVE); + + private final HttpURLConnection connection; + private final byte[] responseData; + private final boolean typeImage; + + public DownloadFailedException(HttpURLConnection connection, byte[] responseData) throws IOException { + this(connection, responseData, null); + } + + public DownloadFailedException(HttpURLConnection connection, byte[] responseData, Throwable cause) + throws IOException { + super("HTTP error: " + connection.getResponseCode(), cause); + this.connection = connection; + this.responseData = responseData; + this.typeImage = ImageFormatDetector.getImageType(responseData) != null; + } + + public int getHttpResponseCode() { + try { + return connection.getResponseCode(); + } catch (IOException e) { + return -1; + } + } + + public boolean isTypeImage() { + return typeImage; + } + + public byte[] getResponseData() { + return responseData; + } + + public String generateResponseErrorText() { + try { + String contentType = Objects.requireNonNullElse(connection.getContentType(), ""); + String payload = ""; + + if (responseData != null + && StringUtils.startsWithAny(contentType, "text/", "application/xml", "application/json")) { + Matcher charsetMatcher = CHARSET.matcher(contentType); + Charset contentCharset = StandardCharsets.UTF_8; + try { + if (charsetMatcher.find()) { + contentCharset = Charset.forName(charsetMatcher.group(1)); + } else if (contentType.contains("html")) { + String responseString = new String(responseData, StandardCharsets.UTF_8); + charsetMatcher = CHARSET.matcher(responseString); + if (charsetMatcher.find()) { + contentCharset = Charset.forName(charsetMatcher.group(1)); + } + } + } catch (IllegalArgumentException e) { + // ignore and continue with default charset + } + int contentTypeEnd = contentType.indexOf(';'); + if (contentTypeEnd > 0) { + contentType = contentType.substring(0, contentTypeEnd).trim(); + } + payload = new String(responseData, contentCharset); + if (contentType.contains("html")) { + payload = HtmlStrip.getInnerText(payload, "body"); + payload = HtmlStrip.getInnerText(payload, "html"); + payload = payload.replaceAll("<[^>]+>", " "); // remove all tags + payload = payload.replaceAll("( *\\r?\\n *)+", "\n"); // simplify new-lines + payload = payload.replaceAll("[ ]{2,}", " "); // simplify spaces + log.debug(payload); + } + payload = "\n" + payload; + } + return connection.getURL() + "\n" + "> " + connection.getResponseCode() + " " + + connection.getResponseMessage() + "\ncontent type: " + connection.getContentType() + payload; + } catch (Exception e) { + log.error("Failed to generate response error text", e); + return "Unknown error " + e.getClass().getSimpleName() + "\n" + e.getMessage(); + } + } + + @Override + public String getMessage() { + return super.getMessage() + " " + connection.getURL(); + } + +} diff --git a/src/main/java/mobac/exceptions/InvalidNameException.java b/mobac/src/main/java/mobac/exceptions/InvalidNameException.java similarity index 89% rename from src/main/java/mobac/exceptions/InvalidNameException.java rename to mobac/src/main/java/mobac/exceptions/InvalidNameException.java index 5f18648..85300e1 100644 --- a/src/main/java/mobac/exceptions/InvalidNameException.java +++ b/mobac/src/main/java/mobac/exceptions/InvalidNameException.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.exceptions; diff --git a/src/main/java/mobac/exceptions/MOBACOutOfMemoryException.java b/mobac/src/main/java/mobac/exceptions/MOBACOutOfMemoryException.java similarity index 92% rename from src/main/java/mobac/exceptions/MOBACOutOfMemoryException.java rename to mobac/src/main/java/mobac/exceptions/MOBACOutOfMemoryException.java index 93631f6..4f7e4ec 100644 --- a/src/main/java/mobac/exceptions/MOBACOutOfMemoryException.java +++ b/mobac/src/main/java/mobac/exceptions/MOBACOutOfMemoryException.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.exceptions; diff --git a/src/main/java/mobac/exceptions/MapCreationException.java b/mobac/src/main/java/mobac/exceptions/MapCreationException.java similarity index 89% rename from src/main/java/mobac/exceptions/MapCreationException.java rename to mobac/src/main/java/mobac/exceptions/MapCreationException.java index ea9715b..c66c23e 100644 --- a/src/main/java/mobac/exceptions/MapCreationException.java +++ b/mobac/src/main/java/mobac/exceptions/MapCreationException.java @@ -1,32 +1,32 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.exceptions; -import java.io.StringWriter; - import mobac.program.interfaces.ExceptionExtendedInfo; import mobac.program.interfaces.MapInterface; import mobac.program.interfaces.MapSource; import mobac.program.model.MapSourceLoaderInfo; +import java.io.StringWriter; + public class MapCreationException extends Exception implements ExceptionExtendedInfo { private static final long serialVersionUID = 1L; - private MapInterface map; + private final MapInterface map; public MapCreationException(String message, MapInterface map, Throwable cause) { super(message, cause); @@ -52,8 +52,9 @@ public class MapCreationException extends Exception implements ExceptionExtended MapSourceLoaderInfo loaderInfo = map.getMapSource().getLoaderInfo(); if (loaderInfo != null) { sw.append("\nMap type: " + loaderInfo.getLoaderType()); - if (loaderInfo.getSourceFile() != null) + if (loaderInfo.getSourceFile() != null) { sw.append("\nMap implementation: " + loaderInfo.getSourceFile().getName()); + } sw.append("\nMap revision: " + loaderInfo.getRevision()); } } diff --git a/src/main/java/mobac/exceptions/MapDownloadSkippedException.java b/mobac/src/main/java/mobac/exceptions/MapDownloadSkippedException.java similarity index 78% rename from src/main/java/mobac/exceptions/MapDownloadSkippedException.java rename to mobac/src/main/java/mobac/exceptions/MapDownloadSkippedException.java index 4ab8585..05d7a01 100644 --- a/src/main/java/mobac/exceptions/MapDownloadSkippedException.java +++ b/mobac/src/main/java/mobac/exceptions/MapDownloadSkippedException.java @@ -1,26 +1,27 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.exceptions; import mobac.program.AtlasThread; /** - * Thrown in {@link AtlasThread#createMap(mobac.program.interfaces.MapInterface)} - * if the user chose to skip that map because of download problems. + * Thrown in + * {@link AtlasThread#createMap(mobac.program.interfaces.MapInterface)} if the + * user chose to skip that map because of download problems. */ public class MapDownloadSkippedException extends Exception { diff --git a/src/main/java/mobac/exceptions/MapSourceCreateException.java b/mobac/src/main/java/mobac/exceptions/MapSourceCreateException.java similarity index 89% rename from src/main/java/mobac/exceptions/MapSourceCreateException.java rename to mobac/src/main/java/mobac/exceptions/MapSourceCreateException.java index 42acafc..2fdb25d 100644 --- a/src/main/java/mobac/exceptions/MapSourceCreateException.java +++ b/mobac/src/main/java/mobac/exceptions/MapSourceCreateException.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.exceptions; diff --git a/src/main/java/mobac/exceptions/MapSourceInitializationException.java b/mobac/src/main/java/mobac/exceptions/MapSourceInitializationException.java similarity index 90% rename from src/main/java/mobac/exceptions/MapSourceInitializationException.java rename to mobac/src/main/java/mobac/exceptions/MapSourceInitializationException.java index 414db81..33b0ddf 100644 --- a/src/main/java/mobac/exceptions/MapSourceInitializationException.java +++ b/mobac/src/main/java/mobac/exceptions/MapSourceInitializationException.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.exceptions; diff --git a/src/main/java/mobac/exceptions/MapSourcesUpdateException.java b/mobac/src/main/java/mobac/exceptions/MapSourcesUpdateException.java similarity index 83% rename from src/main/java/mobac/exceptions/MapSourcesUpdateException.java rename to mobac/src/main/java/mobac/exceptions/MapSourcesUpdateException.java index 0c538d1..9fe82f9 100644 --- a/src/main/java/mobac/exceptions/MapSourcesUpdateException.java +++ b/mobac/src/main/java/mobac/exceptions/MapSourcesUpdateException.java @@ -1,31 +1,27 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.exceptions; -import mobac.mapsources.MapSourcesManager; - /** * Encapsulates several other exceptions that may occur while performing an * mapsources online update. - * - * @see MapSourcesManager#mapsourcesOnlineUpdate() */ public class MapSourcesUpdateException extends Exception { - + private static final long serialVersionUID = 1L; public MapSourcesUpdateException(String message) { diff --git a/mobac/src/main/java/mobac/exceptions/NotImplementedException.java b/mobac/src/main/java/mobac/exceptions/NotImplementedException.java new file mode 100644 index 0000000..beed5ec --- /dev/null +++ b/mobac/src/main/java/mobac/exceptions/NotImplementedException.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.exceptions; + +public class NotImplementedException extends RuntimeException { + + private static final String NOT_IMPLEMENTED = "Method not implemented"; + + public NotImplementedException() { + super(NOT_IMPLEMENTED); + } + + public NotImplementedException(Throwable cause) { + super(NOT_IMPLEMENTED, cause); + } + + public NotImplementedException(Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(NOT_IMPLEMENTED, cause, enableSuppression, writableStackTrace); + } + +} diff --git a/src/main/java/mobac/exceptions/StopAllDownloadsException.java b/mobac/src/main/java/mobac/exceptions/StopAllDownloadsException.java similarity index 90% rename from src/main/java/mobac/exceptions/StopAllDownloadsException.java rename to mobac/src/main/java/mobac/exceptions/StopAllDownloadsException.java index fecf16d..a93a36b 100644 --- a/src/main/java/mobac/exceptions/StopAllDownloadsException.java +++ b/mobac/src/main/java/mobac/exceptions/StopAllDownloadsException.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.exceptions; diff --git a/src/main/java/mobac/exceptions/TileException.java b/mobac/src/main/java/mobac/exceptions/TileException.java similarity index 89% rename from src/main/java/mobac/exceptions/TileException.java rename to mobac/src/main/java/mobac/exceptions/TileException.java index 347fdf8..d957e6d 100644 --- a/src/main/java/mobac/exceptions/TileException.java +++ b/mobac/src/main/java/mobac/exceptions/TileException.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.exceptions; diff --git a/src/main/java/mobac/exceptions/TileStoreException.java b/mobac/src/main/java/mobac/exceptions/TileStoreException.java similarity index 90% rename from src/main/java/mobac/exceptions/TileStoreException.java rename to mobac/src/main/java/mobac/exceptions/TileStoreException.java index a5c0b9e..bdba201 100644 --- a/src/main/java/mobac/exceptions/TileStoreException.java +++ b/mobac/src/main/java/mobac/exceptions/TileStoreException.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.exceptions; @@ -31,5 +31,5 @@ public class TileStoreException extends DatabaseException { public TileStoreException(String message, Throwable t) { super(message, t); } - + } diff --git a/src/main/java/mobac/exceptions/UnrecoverableDownloadException.java b/mobac/src/main/java/mobac/exceptions/UnrecoverableDownloadException.java similarity index 90% rename from src/main/java/mobac/exceptions/UnrecoverableDownloadException.java rename to mobac/src/main/java/mobac/exceptions/UnrecoverableDownloadException.java index 3079d5c..c3fe816 100644 --- a/src/main/java/mobac/exceptions/UnrecoverableDownloadException.java +++ b/mobac/src/main/java/mobac/exceptions/UnrecoverableDownloadException.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.exceptions; @@ -25,24 +25,23 @@ package mobac.exceptions; public class UnrecoverableDownloadException extends TileException { private static final long serialVersionUID = 1L; - + public static int ERROR_CODE_NORMAL = 0; public static int ERROR_CODE_CONTENT_TYPE = 1; - + private int errorCode = ERROR_CODE_NORMAL; public UnrecoverableDownloadException(String message) { super(message); errorCode = ERROR_CODE_NORMAL; } - + public UnrecoverableDownloadException(String message, int errorCode) { super(message); this.errorCode = errorCode; } - - public int getErrorCode() - { + + public int getErrorCode() { return errorCode; } diff --git a/mobac/src/main/java/mobac/exceptions/UnsupportedDataTypeException.java b/mobac/src/main/java/mobac/exceptions/UnsupportedDataTypeException.java new file mode 100644 index 0000000..261a57c --- /dev/null +++ b/mobac/src/main/java/mobac/exceptions/UnsupportedDataTypeException.java @@ -0,0 +1,10 @@ +package mobac.exceptions; + +import java.io.IOException; + +public class UnsupportedDataTypeException extends IOException { + + public UnsupportedDataTypeException(String dataType) { + super("Unsupported data type: " + dataType); + } +} diff --git a/src/main/java/mobac/exceptions/UpdateFailedException.java b/mobac/src/main/java/mobac/exceptions/UpdateFailedException.java similarity index 89% rename from src/main/java/mobac/exceptions/UpdateFailedException.java rename to mobac/src/main/java/mobac/exceptions/UpdateFailedException.java index abcfe4e..05624a4 100644 --- a/src/main/java/mobac/exceptions/UpdateFailedException.java +++ b/mobac/src/main/java/mobac/exceptions/UpdateFailedException.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.exceptions; diff --git a/src/main/java/mobac/externaltools/ExternalToolDef.java b/mobac/src/main/java/mobac/externaltools/ExternalToolDef.java similarity index 53% rename from src/main/java/mobac/externaltools/ExternalToolDef.java rename to mobac/src/main/java/mobac/externaltools/ExternalToolDef.java index 753f3cd..f51217d 100644 --- a/src/main/java/mobac/externaltools/ExternalToolDef.java +++ b/mobac/src/main/java/mobac/externaltools/ExternalToolDef.java @@ -1,41 +1,40 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.externaltools; +import jakarta.xml.bind.annotation.XmlList; +import jakarta.xml.bind.annotation.XmlRootElement; +import mobac.gui.MainGUI; +import mobac.program.model.MapSelection; +import mobac.utilities.GUIExceptionHandler; +import mobac.utilities.I18nUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.JOptionPane; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; -import javax.swing.JOptionPane; -import javax.xml.bind.annotation.XmlList; -import javax.xml.bind.annotation.XmlRootElement; - -import mobac.gui.MainGUI; -import mobac.program.model.MapSelection; -import mobac.utilities.GUIExceptionHandler; -import mobac.utilities.I18nUtils; - -import org.apache.log4j.Logger; - @XmlRootElement(name = "ExternalTool") public class ExternalToolDef implements ActionListener { - private static final Logger log = Logger.getLogger(ExternalToolDef.class); + private static final Logger log = LoggerFactory.getLogger(ExternalToolDef.class); /** * Name used for the menu entry in MOBAC @@ -43,7 +42,8 @@ public class ExternalToolDef implements ActionListener { public String name; /** - * For starting a commandline-script on Windows use cmd /c start mybatch.cmd + * For starting a commandline-script on Windows use + * cmd /c start mybatch.cmd */ public String command; @@ -53,8 +53,9 @@ public class ExternalToolDef implements ActionListener { public List parameters = new ArrayList(); private boolean mapSelNull(MapSelection mapSel) { - if (mapSel != null) + if (mapSel != null) { return false; + } JOptionPane.showMessageDialog(MainGUI.getMainGUI(), I18nUtils.localizedStringForKey("msg_tools_exec_error_selected_area"), I18nUtils.localizedStringForKey("Error"), JOptionPane.ERROR_MESSAGE); @@ -72,58 +73,63 @@ public class ExternalToolDef implements ActionListener { for (ToolParameters param : parameters) { String add = ""; switch (param) { - case MAX_LAT: - if (mapSelNull(mapSel)) - return; - add = Double.toString(mapSel.getMax().lat); - break; - case MIN_LAT: - if (mapSelNull(mapSel)) - return; - add = Double.toString(mapSel.getMin().lat); - break; - case MAX_LON: - if (mapSelNull(mapSel)) - return; - add = Double.toString(mapSel.getMax().lon); - break; - case MIN_LON: - if (mapSelNull(mapSel)) - return; - add = Double.toString(mapSel.getMin().lon); - break; - case MAX_ZOOM: - if (zooms.length == 0) { - JOptionPane.showMessageDialog(gui, - I18nUtils.localizedStringForKey("msg_no_zoom_level_selected"), - I18nUtils.localizedStringForKey("Error"), JOptionPane.ERROR_MESSAGE); - return; - } - add = Integer.toString(zooms[zooms.length - 1]); - break; - case MIN_ZOOM: - if (zooms.length == 0) { - JOptionPane.showMessageDialog(gui, - I18nUtils.localizedStringForKey("msg_no_zoom_level_selected"), - I18nUtils.localizedStringForKey("Error"), JOptionPane.ERROR_MESSAGE); - return; - } - add = Integer.toString(zooms[0]); - break; - case MAPSOURCE_NAME: - add = gui.previewMap.getMapSource().getName(); - break; - case MAPSOURCE_DISPLAYNAME: - add = gui.previewMap.getMapSource().toString(); - break; - case NAME_EDITBOX: - add = gui.getUserText(); - break; - default: - throw new RuntimeException("Unsupported parameter type: " + param); + case MAX_LAT : + if (mapSelNull(mapSel)) { + return; + } + add = Double.toString(mapSel.getMax().lat); + break; + case MIN_LAT : + if (mapSelNull(mapSel)) { + return; + } + add = Double.toString(mapSel.getMin().lat); + break; + case MAX_LON : + if (mapSelNull(mapSel)) { + return; + } + add = Double.toString(mapSel.getMax().lon); + break; + case MIN_LON : + if (mapSelNull(mapSel)) { + return; + } + add = Double.toString(mapSel.getMin().lon); + break; + case MAX_ZOOM : + if (zooms.length == 0) { + JOptionPane.showMessageDialog(gui, + I18nUtils.localizedStringForKey("msg_no_zoom_level_selected"), + I18nUtils.localizedStringForKey("Error"), JOptionPane.ERROR_MESSAGE); + return; + } + add = Integer.toString(zooms[zooms.length - 1]); + break; + case MIN_ZOOM : + if (zooms.length == 0) { + JOptionPane.showMessageDialog(gui, + I18nUtils.localizedStringForKey("msg_no_zoom_level_selected"), + I18nUtils.localizedStringForKey("Error"), JOptionPane.ERROR_MESSAGE); + return; + } + add = Integer.toString(zooms[0]); + break; + case MAPSOURCE_NAME : + add = gui.previewMap.getMapSource().getName(); + break; + case MAPSOURCE_DISPLAYNAME : + add = gui.previewMap.getMapSource().toString(); + break; + case NAME_EDITBOX : + add = gui.getUserText(); + break; + default : + throw new RuntimeException("Unsupported parameter type: " + param); } - if (add.indexOf(' ') >= 0) + if (add.indexOf(' ') >= 0) { add = "\"" + add + "\""; + } executeCommand += " " + add; } if (debug) { @@ -131,8 +137,9 @@ public class ExternalToolDef implements ActionListener { String.format(I18nUtils.localizedStringForKey("msg_tools_exec_command_ask"), executeCommand), I18nUtils.localizedStringForKey("msg_tools_exec_command_ask_title"), JOptionPane.OK_CANCEL_OPTION); - if (r != JOptionPane.OK_OPTION) + if (r != JOptionPane.OK_OPTION) { return; + } } log.debug("Executing " + executeCommand); Runtime.getRuntime().exec(executeCommand); diff --git a/src/main/java/mobac/externaltools/ExternalToolsLoader.java b/mobac/src/main/java/mobac/externaltools/ExternalToolsLoader.java similarity index 80% rename from src/main/java/mobac/externaltools/ExternalToolsLoader.java rename to mobac/src/main/java/mobac/externaltools/ExternalToolsLoader.java index 5aba164..b878388 100644 --- a/src/main/java/mobac/externaltools/ExternalToolsLoader.java +++ b/mobac/src/main/java/mobac/externaltools/ExternalToolsLoader.java @@ -1,44 +1,41 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.externaltools; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBException; +import jakarta.xml.bind.Marshaller; +import jakarta.xml.bind.Unmarshaller; +import mobac.program.DirectoryManager; +import mobac.utilities.GUIExceptionHandler; +import mobac.utilities.file.FileExtFilter; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.LinkedList; import java.util.List; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; - -import mobac.program.DirectoryManager; -import mobac.utilities.GUIExceptionHandler; -import mobac.utilities.Utilities; -import mobac.utilities.file.FileExtFilter; - -import org.w3c.dom.Document; - public class ExternalToolsLoader { public static List tools = null; @@ -50,8 +47,9 @@ public class ExternalToolsLoader { public static boolean load() { try { File dir = DirectoryManager.toolsDir; - if (!dir.isDirectory()) + if (!dir.isDirectory()) { return false; + } File[] files = dir.listFiles(new FileExtFilter(".xml")); tools = new LinkedList(); for (File f : files) { @@ -67,9 +65,7 @@ public class ExternalToolsLoader { public static ExternalToolDef loadFile(File f) throws JAXBException { JAXBContext context = JAXBContext.newInstance(ExternalToolDef.class); Unmarshaller unmarshaller = context.createUnmarshaller(); - InputStream is = null; - try { - is = new FileInputStream(f); + try (InputStream is = new FileInputStream(f)) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder loader = factory.newDocumentBuilder(); @@ -79,8 +75,6 @@ public class ExternalToolsLoader { throw e; } catch (Exception e) { throw new JAXBException(e); - } finally { - Utilities.closeStream(is); } } @@ -88,18 +82,14 @@ public class ExternalToolsLoader { JAXBContext context = JAXBContext.newInstance(ExternalToolDef.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); - OutputStream os = null; - try { - os = new FileOutputStream(f); + try (OutputStream os = new FileOutputStream(f)) { marshaller.marshal(toolsDef, os); - } catch (FileNotFoundException e) { + } catch (IOException e) { throw new JAXBException(e); - } finally { - Utilities.closeStream(os); } } - public static final void main(String[] args) { + public static void main(String[] args) { try { ExternalToolDef t = new ExternalToolDef(); t.command = "command"; diff --git a/src/main/java/mobac/externaltools/ToolParameters.java b/mobac/src/main/java/mobac/externaltools/ToolParameters.java similarity index 85% rename from src/main/java/mobac/externaltools/ToolParameters.java rename to mobac/src/main/java/mobac/externaltools/ToolParameters.java index 501ab84..85d8f00 100644 --- a/src/main/java/mobac/externaltools/ToolParameters.java +++ b/mobac/src/main/java/mobac/externaltools/ToolParameters.java @@ -1,26 +1,26 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.externaltools; public enum ToolParameters { - MAX_LAT, MIN_LAT, MAX_LON, MIN_LON, // + MAX_LAT, MIN_LAT, MAX_LON, MIN_LON, // MIN_ZOOM, MAX_ZOOM, // minimum and maximum of selected zoom levels check-boxes - MAPSOURCE_NAME, MAPSOURCE_DISPLAYNAME, // Currently select map source internal or display name + MAPSOURCE_NAME, MAPSOURCE_DISPLAYNAME, // Currently select map source internal or display name NAME_EDITBOX // content of the edit box "Name" in the side panel "Atlas Content" } diff --git a/src/main/java/mobac/gui/AtlasProgress.java b/mobac/src/main/java/mobac/gui/AtlasProgress.java similarity index 82% rename from src/main/java/mobac/gui/AtlasProgress.java rename to mobac/src/main/java/mobac/gui/AtlasProgress.java index 8b97586..b3e929d 100644 --- a/src/main/java/mobac/gui/AtlasProgress.java +++ b/mobac/src/main/java/mobac/gui/AtlasProgress.java @@ -1,21 +1,50 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui; +import mobac.program.AtlasThread; +import mobac.program.Logging; +import mobac.program.interfaces.AtlasInterface; +import mobac.program.interfaces.LayerInterface; +import mobac.program.interfaces.MapInterface; +import mobac.program.interfaces.MapSourceListener; +import mobac.program.model.Atlas; +import mobac.program.model.AtlasOutputFormat; +import mobac.program.model.Settings; +import mobac.utilities.GBC; +import mobac.utilities.GUIExceptionHandler; +import mobac.utilities.I18nUtils; +import mobac.utilities.OSUtilities; +import mobac.utilities.Utilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.Box; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.SwingUtilities; +import javax.swing.ToolTipManager; +import javax.swing.UIManager; +import javax.swing.border.EmptyBorder; +import java.awt.BorderLayout; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; @@ -30,83 +59,29 @@ import java.util.ArrayList; import java.util.Timer; import java.util.TimerTask; -import javax.swing.Box; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JProgressBar; -import javax.swing.SwingUtilities; -import javax.swing.ToolTipManager; -import javax.swing.UIManager; - -import mobac.program.AtlasThread; -import mobac.program.Logging; -import mobac.program.interfaces.AtlasInterface; -import mobac.program.interfaces.LayerInterface; -import mobac.program.interfaces.MapInterface; -import mobac.program.interfaces.MapSourceListener; -import mobac.program.model.AtlasOutputFormat; -import mobac.program.model.Settings; -import mobac.utilities.GBC; -import mobac.utilities.GUIExceptionHandler; -import mobac.utilities.I18nUtils; -import mobac.utilities.OSUtilities; -import mobac.utilities.Utilities; - -import org.apache.log4j.Logger; - /** - * A window showing the progress while {@link AtlasThread} downloads and processes the map tiles. - * + * A window showing the progress while {@link AtlasThread} downloads and + * processes the map tiles. */ public class AtlasProgress extends JFrame implements ActionListener, MapSourceListener { - private static Logger log = Logger.getLogger(AtlasProgress.class); - private static final long serialVersionUID = -1L; - private static final Timer TIMER = new Timer(true); - + private static final Logger log = LoggerFactory.getLogger(AtlasProgress.class); + private static final String TEXT_MAP_DOWNLOAD = I18nUtils.localizedStringForKey("dlg_download_zoom_level_progress"); + private static final String TEXT_PERCENT = I18nUtils.localizedStringForKey("dlg_download_done_percent"); + private static final String TEXT_TENTHPERCENT = I18nUtils.localizedStringForKey("dlg_download_done_tenthpercent"); + private final Data data = new Data(); + private final AtlasThread atlasThread; private JProgressBar atlasProgressBar; private JProgressBar mapDownloadProgressBar; private JProgressBar mapCreationProgressBar; - - private Container background; - + private JPanel background; private long initialTotalTime; private long initialMapDownloadTime; - - private static class Data { - AtlasInterface atlasInterface; - MapInterface map; - MapInfo mapInfo; - long numberOfDownloadedBytes = 0; - long numberOfBytesLoadedFromCache = 0; - int totalNumberOfTiles = 0; - int totalNumberOfMaps = 0; - int totalProgress = 0; - int totalProgressTenthPercent = -1; - int currentMapNumber = 0; - int mapDownloadProgress = 0; - int mapDownloadNumberOfTiles = 0; - int mapCreationProgress = 0; - int mapCreationMax = 0; - int mapRetryErrors = 0; - int mapPermanentErrors = 0; - int prevMapsRetryErrors = 0; - int prevMapsPermanentErrors = 0; - boolean paused = false; - } - - private final Data data = new Data(); - private boolean aborted = false; private boolean finished = false; - private JLabel windowTitle; - private JLabel title; private JLabel mapInfoLabel; private JLabel mapDownloadTitle; @@ -131,52 +106,43 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi private JLabel permanentDownloadErrorsValue; private JLabel totalDownloadTime; private JLabel totalDownloadTimeValue; - private JCheckBox ignoreDlErrors; private JLabel statusLabel; - private JButton dismissWindowButton; private JButton openProgramFolderButton; private JButton abortAtlasCreationButton; private JButton pauseResumeDownloadButton; - private AtlasCreationController downloadControlListener = null; - private UpdateTask updateTask = null; private GUIUpdater guiUpdater = null; - - private AtlasThread atlasThread; - private ArrayList mapInfos = null; - private static String TEXT_MAP_DOWNLOAD = I18nUtils.localizedStringForKey("dlg_download_zoom_level_progress"); - private static String TEXT_PERCENT = I18nUtils.localizedStringForKey("dlg_download_done_percent"); - private static String TEXT_TENTHPERCENT = I18nUtils.localizedStringForKey("dlg_download_done_tenthpercent"); - public AtlasProgress(AtlasThread atlasThread) { super(I18nUtils.localizedStringForKey("dlg_download_title")); this.atlasThread = atlasThread; ToolTipManager.sharedInstance().setDismissDelay(12000); if (MainGUI.getMainGUI() == null) // Atlas creation started via command-line, no MainGUi available + { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - else + } else { setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + } setIconImages(MainGUI.MOBAC_ICONS); - setLayout(new GridBagLayout()); updateTask = new UpdateTask(); guiUpdater = new GUIUpdater(); createComponents(); // Initialize the layout in respect to the layout (font size ...) pack(); + setMinimumSize(new Dimension(getWidth(), getHeight() + 20)); guiUpdater.run(); // The layout is now initialized - we disable it because we don't want // want to the labels to jump around if the content changes. - background.setLayout(null); - setResizable(false); + // background.setLayout(null); + // setResizable(false); Dimension dScreen = Toolkit.getDefaultToolkit().getScreenSize(); Dimension dContent = getSize(); @@ -188,10 +154,26 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi addWindowListener(new CloseListener()); } + public static void main(String[] args) { + Logging.configureLogging(); + GUIExceptionHandler.installToolkitEventQueueProxy(); + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + log.error("The selection of look and feel failed!", e); + } + AtlasProgress ap = new AtlasProgress(null); + Atlas atlas = Atlas.newInstance(); + atlas.setName("Atlas name"); + ap.initAtlas(atlas); + ap.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + ap.setVisible(true); + } + private void createComponents() { background = new JPanel(new GridBagLayout()); - windowTitle = new JLabel(I18nUtils.localizedStringForKey("dlg_download_window_title")); + windowTitle = new JLabel(I18nUtils.localizedStringForKey("dlg_download_window_title", "")); title = new JLabel(I18nUtils.localizedStringForKey("dlg_download_map_progress")); @@ -243,8 +225,8 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi dismissWindowButton.setToolTipText(I18nUtils.localizedStringForKey("dlg_download_btn_close_win_tips_disable")); dismissWindowButton.setVisible(false); openProgramFolderButton = new JButton(I18nUtils.localizedStringForKey("dlg_download_btn_open_folder")); - openProgramFolderButton.setToolTipText(I18nUtils - .localizedStringForKey("dlg_download_btn_open_folder_tips_disabled")); + openProgramFolderButton + .setToolTipText(I18nUtils.localizedStringForKey("dlg_download_btn_open_folder_tips_disabled")); openProgramFolderButton.setEnabled(false); pauseResumeDownloadButton = new JButton(I18nUtils.localizedStringForKey("dlg_download_btn_pause_resume")); @@ -253,8 +235,8 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi GBC gbcEolFill = GBC.eol().fill(GBC.HORIZONTAL); GBC gbcEolFillI = GBC.eol().fill(GBC.HORIZONTAL).insets(0, 5, 0, 0); - // background.add(windowTitle, gbcEolFill); - // background.add(Box.createVerticalStrut(10), gbcEol); + background.add(windowTitle, gbcEolFill); + background.add(Box.createVerticalStrut(10), gbcEol); background.add(mapInfoLabel, gbcEolFill); background.add(Box.createVerticalStrut(20), gbcEol); @@ -295,7 +277,7 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi infoPanel.add(totalDownloadTimeValue, gbci.toggleEol()); JPanel bottomPanel = new JPanel(new GridBagLayout()); - bottomPanel.add(infoPanel, GBC.std().gridheight(2).fillH()); + bottomPanel.add(infoPanel, GBC.std().gridheight(2).fill()); bottomPanel.add(ignoreDlErrors, GBC.eol().anchor(GBC.EAST)); bottomPanel.add(statusLabel, GBC.eol().anchor(GBC.CENTER)); @@ -308,11 +290,12 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi bottomPanel.add(openProgramFolderButton, gbcRight); background.add(bottomPanel, gbcEolFillI); + background.add(Box.createVerticalStrut(10), gbcEol); + background.setBorder(new EmptyBorder(10, 10, 10, 10)); - JPanel borderPanel = new JPanel(new GridBagLayout()); - borderPanel.add(background, GBC.std().insets(10, 10, 10, 10).fill()); - - add(borderPanel, GBC.std().fill()); + Container contentPanel = getContentPane(); + contentPanel.setLayout(new BorderLayout()); + contentPanel.add(background, BorderLayout.NORTH); abortAtlasCreationButton.addActionListener(this); dismissWindowButton.addActionListener(this); @@ -322,13 +305,14 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi public void initAtlas(AtlasInterface atlasInterface) { data.atlasInterface = atlasInterface; - if (atlasInterface.getOutputFormat().equals(AtlasOutputFormat.TILESTORE)) + if (atlasInterface.getOutputFormat().equals(AtlasOutputFormat.TILESTORE)) { data.totalNumberOfTiles = (int) atlasInterface.calculateTilesToDownload(); - else + } else { data.totalNumberOfTiles = (int) atlasInterface.calculateTilesToDownload() * 2; + } int mapCount = 0; int tileCount = 0; - mapInfos = new ArrayList(100); + mapInfos = new ArrayList<>(100); for (LayerInterface layer : atlasInterface) { mapCount += layer.getMapCount(); for (MapInterface map : layer) { @@ -365,7 +349,7 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi /** * Initialize the GUI progress bars - * + * * @param maxTilesToProcess */ public void initMapCreation(int maxTilesToProcess) { @@ -420,6 +404,10 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi updateGUI(); } + @Override + public void tileDownloadStarted(String tileUrl) { + } + private String formatTime(long longSeconds) { String timeString = ""; @@ -428,21 +416,23 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi } else { int minutes = (int) (longSeconds / 60); int seconds = (int) (longSeconds % 60); - if (minutes > 0) - timeString += Integer.toString(minutes) - + " " - + (minutes == 1 ? I18nUtils.localizedStringForKey("minute") : I18nUtils - .localizedStringForKey("minutes")) + " "; - timeString += Integer.toString(seconds) - + " " - + (seconds == 1 ? I18nUtils.localizedStringForKey("second") : I18nUtils - .localizedStringForKey("seconds")); + if (minutes > 0) { + timeString += minutes + " " + + (minutes == 1 + ? I18nUtils.localizedStringForKey("minute") + : I18nUtils.localizedStringForKey("minutes")) + + " "; + } + timeString += seconds + " " + + (seconds == 1 + ? I18nUtils.localizedStringForKey("second") + : I18nUtils.localizedStringForKey("seconds")); } return timeString; } public void setZoomLevel(int theZoomLevel) { - mapDownloadTitle.setText(TEXT_MAP_DOWNLOAD + Integer.toString(theZoomLevel)); + mapDownloadTitle.setText(TEXT_MAP_DOWNLOAD + theZoomLevel); } public void atlasCreationFinished() { @@ -455,10 +445,8 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi abortAtlasCreationButton.setEnabled(false); if (aborted) { - windowTitle.setText(I18nUtils.localizedStringForKey("dlg_download_abort_window_title")); setTitle(I18nUtils.localizedStringForKey("dlg_download_abort_title")); } else { - windowTitle.setText(I18nUtils.localizedStringForKey("dlg_download_succeed_window_title")); setTitle(I18nUtils.localizedStringForKey("dlg_download_succeed_title")); } // mapInfoLabel.setText(""); @@ -467,13 +455,13 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi abortAtlasCreationButton.setVisible(false); - dismissWindowButton.setToolTipText(I18nUtils - .localizedStringForKey("dlg_download_btn_close_win_tips_enable")); + dismissWindowButton + .setToolTipText(I18nUtils.localizedStringForKey("dlg_download_btn_close_win_tips_enable")); dismissWindowButton.setVisible(true); if (!aborted) { - openProgramFolderButton.setToolTipText(I18nUtils - .localizedStringForKey("dlg_download_btn_open_folder_tips_enabled")); + openProgramFolderButton.setToolTipText( + I18nUtils.localizedStringForKey("dlg_download_btn_open_folder_tips_enabled")); openProgramFolderButton.setEnabled(true); } } @@ -502,7 +490,7 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi return downloadControlListener; } - public void setDownloadControlerListener(AtlasCreationController threadControlListener) { + public void setDownloadControllerListener(AtlasCreationController threadControlListener) { this.downloadControlListener = threadControlListener; } @@ -521,13 +509,15 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi } else if (abortAtlasCreationButton.equals(source)) { aborted = true; stopUpdateTask(); - if (downloadControlListener != null) + if (downloadControlListener != null) { downloadControlListener.abortAtlasCreation(); - else + } else { closeWindow(); + } } else if (pauseResumeDownloadButton.equals(source)) { - if (downloadControlListener != null) + if (downloadControlListener != null) { downloadControlListener.pauseResumeAtlasCreation(); + } } } @@ -539,163 +529,36 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi SwingUtilities.invokeLater(guiUpdater); } - private class GUIUpdater implements Runnable { + public interface AtlasCreationController { - int scheduledCounter = 0; + void abortAtlasCreation(); - public void updateAsynchronously() { - // If there is still at least one scheduled update request to be - // executed we don't have add another one as this can result in an - // to overloaded swing invocation queue. - synchronized (this) { - if (scheduledCounter > 0) - return; - scheduledCounter++; - } - SwingUtilities.invokeLater(this); - } + void pauseResumeAtlasCreation(); - public void run() { - synchronized (this) { - scheduledCounter--; - } + boolean isPaused(); - if (data.map != null) { - String text = String.format(I18nUtils.localizedStringForKey("dlg_download_map_info_label"), - data.map.getName(), data.map.getLayer().getName(), data.map.getMapSource().toString()); - mapInfoLabel.setText(text); - } - - // atlas progress - atlasProgressBar.setMaximum(data.totalNumberOfTiles); - atlasProgressBar.setValue(data.totalProgress); - - int newTenthPercent = (int) (data.totalProgress * 1000d / (double) data.totalNumberOfTiles); - try { - boolean pauseState = atlasThread.isPaused(); - String statusText = I18nUtils.localizedStringForKey("dlg_download_status_running"); - if (aborted) - statusText = I18nUtils.localizedStringForKey("dlg_download_status_aborted"); - else if (finished) - statusText = I18nUtils.localizedStringForKey("dlg_download_status_finished"); - else if (pauseState) - statusText = I18nUtils.localizedStringForKey("dlg_download_status_paused"); - else - statusText = I18nUtils.localizedStringForKey("dlg_download_status_running"); - statusLabel.setText(I18nUtils.localizedStringForKey("dlg_download_status_title") + " " + statusText); - - if (data.totalProgressTenthPercent != newTenthPercent || pauseState != data.paused) { - data.totalProgressTenthPercent = newTenthPercent; - atlasPercent.setText(String.format(TEXT_TENTHPERCENT, data.totalProgressTenthPercent / 10.0)); - if (data.atlasInterface != null) { - String text = String.format(I18nUtils.localizedStringForKey("dlg_download_atlas_progress"), - data.totalProgressTenthPercent / 10, data.atlasInterface.getName(), - data.atlasInterface.getOutputFormat()); - if (pauseState) - text += " [" + I18nUtils.localizedStringForKey("dlg_download_status_paused") + "]"; - AtlasProgress.this.setTitle(text); - } - } - data.paused = pauseState; - } catch (NullPointerException e) { - } - - long seconds = -1; - int totalProgress = data.totalProgress; - if (totalProgress != 0) { - // Avoid for a possible division by zero - int totalTilesRemaining = data.totalNumberOfTiles - totalProgress; - long totalElapsedTime = System.currentTimeMillis() - initialTotalTime; - seconds = (totalElapsedTime * totalTilesRemaining / (1000L * totalProgress)); - } - atlasTimeLeft.setText(String.format(I18nUtils.localizedStringForKey("dlg_download_remain_time"), - formatTime(seconds))); - - // layer progress - mapDownloadProgressBar.setMaximum(data.mapDownloadNumberOfTiles); - mapDownloadProgressBar.setValue(data.mapDownloadProgress); - - mapDownloadPercent.setText(String.format(TEXT_PERCENT, - (int) (mapDownloadProgressBar.getPercentComplete() * 100))); - - mapDownloadElementsDone.setText(String.format( - I18nUtils.localizedStringForKey("dlg_download_tile_done_count"), data.mapDownloadProgress, - data.mapDownloadNumberOfTiles)); - - seconds = -1; - int mapDlProgress = data.mapDownloadProgress; - if (mapDlProgress != 0 && initialMapDownloadTime > 0) - seconds = ((System.currentTimeMillis() - initialMapDownloadTime) - * (data.mapDownloadNumberOfTiles - mapDlProgress) / (1000L * mapDlProgress)); - mapDownloadTimeLeft.setText(String.format(I18nUtils.localizedStringForKey("dlg_download_remain_time"), - formatTime(seconds))); - - // map progress - mapCreation.setText(I18nUtils.localizedStringForKey("dlg_download_map_create_title")); - mapCreationProgressBar.setValue(data.mapCreationProgress); - mapCreationProgressBar.setMaximum(data.mapCreationMax); - atlasMapsDone.setText(String.format(I18nUtils.localizedStringForKey("dlg_download_map_done_count"), - (data.currentMapNumber - 1), data.totalNumberOfMaps)); - - // bytes per second - long rate = data.numberOfDownloadedBytes * 1000; - long time = System.currentTimeMillis() - initialMapDownloadTime; - if (data.mapCreationProgress == 0 && initialMapDownloadTime > 0) { - if (time == 0) { - nrOfDownloadedBytesPerSecondValue.setText("??"); - } else { - rate = rate / time; - nrOfDownloadedBytesPerSecondValue.setText(String.format( - I18nUtils.localizedStringForKey("dlg_download_avg_speed_value"), - Utilities.formatBytes(rate))); - } - } - - // downloaded bytes - nrOfDownloadedBytesValue.setText(": " + Utilities.formatBytes(data.numberOfDownloadedBytes)); - nrOfCacheBytesValue.setText(": " + Utilities.formatBytes(data.numberOfBytesLoadedFromCache)); - - // total creation time - long totalSeconds = (System.currentTimeMillis() - initialTotalTime) / 1000; - totalDownloadTimeValue.setText(": " + formatTime(totalSeconds)); - totalDownloadTimeValue.repaint(); - - // active downloads - int activeDownloads = (atlasThread == null) ? 0 : atlasThread.getActiveDownloads(); - activeDownloadsValue.setText(": " + activeDownloads); - activeDownloadsValue.repaint(); - - int totalRetryableErrors = data.prevMapsRetryErrors + data.mapRetryErrors; - retryableDownloadErrorsValue.setText(String.format( - I18nUtils.localizedStringForKey("dlg_download_retry_count_value"), data.mapRetryErrors, - totalRetryableErrors)); - retryableDownloadErrorsValue.repaint(); - int totalPermanentErrors = data.prevMapsPermanentErrors + data.mapPermanentErrors; - permanentDownloadErrorsValue.setText(String.format( - I18nUtils.localizedStringForKey("dlg_download_failed_count_value"), data.mapPermanentErrors, - totalPermanentErrors)); - permanentDownloadErrorsValue.repaint(); - } } - private class UpdateTask extends TimerTask { - - @Override - public void run() { - updateGUI(); - } - } - - private class CloseListener extends WindowAdapter { - - @Override - public void windowClosing(WindowEvent e) { - log.debug("Closing event detected for atlas progress window"); - AtlasCreationController listener = AtlasProgress.this.downloadControlListener; - if (listener != null) - listener.abortAtlasCreation(); - } - + private static class Data { + AtlasInterface atlasInterface; + MapInterface map; + MapInfo mapInfo; + long numberOfDownloadedBytes = 0; + long numberOfBytesLoadedFromCache = 0; + int totalNumberOfTiles = 0; + int totalNumberOfMaps = 0; + int totalProgress = 0; + int totalProgressTenthPercent = -1; + int currentMapNumber = 0; + int mapDownloadProgress = 0; + int mapDownloadNumberOfTiles = 0; + int mapCreationProgress = 0; + int mapCreationMax = 0; + int mapRetryErrors = 0; + int mapPermanentErrors = 0; + int prevMapsRetryErrors = 0; + int prevMapsPermanentErrors = 0; + boolean paused = false; } protected static class MapInfo { @@ -720,32 +583,177 @@ public class AtlasProgress extends JFrame implements ActionListener, MapSourceLi @Override public boolean equals(Object obj) { - if (!(obj instanceof MapInfo)) + if (!(obj instanceof MapInfo)) { return false; + } return map.equals(((MapInfo) obj).map); } } - public static interface AtlasCreationController { + private class GUIUpdater implements Runnable { - public void abortAtlasCreation(); + int scheduledCounter = 0; - public void pauseResumeAtlasCreation(); + public void updateAsynchronously() { + // If there is still at least one scheduled update request to be + // executed we don't have add another one as this can result in an + // to overloaded swing invocation queue. + synchronized (this) { + if (scheduledCounter > 0) { + return; + } + scheduledCounter++; + } + SwingUtilities.invokeLater(this); + } - public boolean isPaused(); + public void run() { + synchronized (this) { + scheduledCounter--; + } + if (data.atlasInterface != null) { + windowTitle.setText( + I18nUtils.localizedStringForKey("dlg_download_window_title", data.atlasInterface.getName())); + } + if (data.map != null) { + String text = String.format(I18nUtils.localizedStringForKey("dlg_download_map_info_label"), + data.map.getName(), data.map.getLayer().getName(), data.map.getMapSource().toString()); + mapInfoLabel.setText(text); + } + + // atlas progress + atlasProgressBar.setMaximum(data.totalNumberOfTiles); + atlasProgressBar.setValue(data.totalProgress); + + int newTenthPercent = (int) (data.totalProgress * 1000d / (double) data.totalNumberOfTiles); + try { + boolean pauseState = atlasThread.isPaused(); + String statusText = I18nUtils.localizedStringForKey("dlg_download_status_running"); + if (aborted) { + statusText = I18nUtils.localizedStringForKey("dlg_download_status_aborted"); + } else if (finished) { + statusText = I18nUtils.localizedStringForKey("dlg_download_status_finished"); + } else if (pauseState) { + statusText = I18nUtils.localizedStringForKey("dlg_download_status_paused"); + } else { + statusText = I18nUtils.localizedStringForKey("dlg_download_status_running"); + } + statusLabel.setText(I18nUtils.localizedStringForKey("dlg_download_status_title") + " " + statusText); + + if (data.totalProgressTenthPercent != newTenthPercent || pauseState != data.paused) { + data.totalProgressTenthPercent = newTenthPercent; + atlasPercent.setText(String.format(TEXT_TENTHPERCENT, data.totalProgressTenthPercent / 10.0)); + if (data.atlasInterface != null) { + String text = String.format(I18nUtils.localizedStringForKey("dlg_download_atlas_progress"), + data.totalProgressTenthPercent / 10, data.atlasInterface.getName(), + data.atlasInterface.getOutputFormat()); + if (pauseState) { + text += " [" + I18nUtils.localizedStringForKey("dlg_download_status_paused") + "]"; + } + AtlasProgress.this.setTitle(text); + } + } + data.paused = pauseState; + } catch (NullPointerException e) { + } + + long seconds = -1; + int totalProgress = data.totalProgress; + if (totalProgress != 0) { + // Avoid for a possible division by zero + int totalTilesRemaining = data.totalNumberOfTiles - totalProgress; + long totalElapsedTime = System.currentTimeMillis() - initialTotalTime; + seconds = (totalElapsedTime * totalTilesRemaining / (1000L * totalProgress)); + } + atlasTimeLeft.setText(I18nUtils.localizedStringForKey("dlg_download_remain_time", formatTime(seconds))); + + // layer progress + mapDownloadProgressBar.setMaximum(data.mapDownloadNumberOfTiles); + mapDownloadProgressBar.setValue(data.mapDownloadProgress); + + mapDownloadPercent + .setText(String.format(TEXT_PERCENT, (int) (mapDownloadProgressBar.getPercentComplete() * 100))); + + mapDownloadElementsDone + .setText(String.format(I18nUtils.localizedStringForKey("dlg_download_tile_done_count"), + data.mapDownloadProgress, data.mapDownloadNumberOfTiles)); + + seconds = -1; + int mapDlProgress = data.mapDownloadProgress; + if (mapDlProgress != 0 && initialMapDownloadTime > 0) { + seconds = ((System.currentTimeMillis() - initialMapDownloadTime) + * (data.mapDownloadNumberOfTiles - mapDlProgress) / (1000L * mapDlProgress)); + } + mapDownloadTimeLeft.setText( + String.format(I18nUtils.localizedStringForKey("dlg_download_remain_time"), formatTime(seconds))); + + // map progress + mapCreation.setText(I18nUtils.localizedStringForKey("dlg_download_map_create_title")); + mapCreationProgressBar.setValue(data.mapCreationProgress); + mapCreationProgressBar.setMaximum(data.mapCreationMax); + atlasMapsDone.setText(String.format(I18nUtils.localizedStringForKey("dlg_download_map_done_count"), + (data.currentMapNumber - 1), data.totalNumberOfMaps)); + + // bytes per second + long rate = data.numberOfDownloadedBytes * 1000; + long time = System.currentTimeMillis() - initialMapDownloadTime; + if (data.mapCreationProgress == 0 && initialMapDownloadTime > 0) { + if (time == 0) { + nrOfDownloadedBytesPerSecondValue.setText("??"); + } else { + rate = rate / time; + nrOfDownloadedBytesPerSecondValue + .setText(String.format(I18nUtils.localizedStringForKey("dlg_download_avg_speed_value"), + Utilities.formatBytes(rate))); + } + } + + // downloaded bytes + nrOfDownloadedBytesValue.setText(": " + Utilities.formatBytes(data.numberOfDownloadedBytes)); + nrOfCacheBytesValue.setText(": " + Utilities.formatBytes(data.numberOfBytesLoadedFromCache)); + + // total creation time + long totalSeconds = (System.currentTimeMillis() - initialTotalTime) / 1000; + totalDownloadTimeValue.setText(": " + formatTime(totalSeconds)); + totalDownloadTimeValue.repaint(); + + // active downloads + int activeDownloads = (atlasThread == null) ? 0 : atlasThread.getActiveDownloads(); + activeDownloadsValue.setText(": " + activeDownloads); + activeDownloadsValue.repaint(); + + int totalRetryableErrors = data.prevMapsRetryErrors + data.mapRetryErrors; + retryableDownloadErrorsValue + .setText(String.format(I18nUtils.localizedStringForKey("dlg_download_retry_count_value"), + data.mapRetryErrors, totalRetryableErrors)); + retryableDownloadErrorsValue.repaint(); + int totalPermanentErrors = data.prevMapsPermanentErrors + data.mapPermanentErrors; + permanentDownloadErrorsValue + .setText(String.format(I18nUtils.localizedStringForKey("dlg_download_failed_count_value"), + data.mapPermanentErrors, totalPermanentErrors)); + permanentDownloadErrorsValue.repaint(); + } } - public static void main(String[] args) { - Logging.configureLogging(); - GUIExceptionHandler.installToolkitEventQueueProxy(); - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch (Exception e) { - log.error("The selection of look and feel failed!", e); + private class UpdateTask extends TimerTask { + + @Override + public void run() { + updateGUI(); } - AtlasProgress ap = new AtlasProgress(null); - ap.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - ap.setVisible(true); + } + + private class CloseListener extends WindowAdapter { + + @Override + public void windowClosing(WindowEvent e) { + log.debug("Closing event detected for atlas progress window"); + AtlasCreationController listener = AtlasProgress.this.downloadControlListener; + if (listener != null) { + listener.abortAtlasCreation(); + } + } + } } diff --git a/src/main/java/mobac/gui/MainGUI.java b/mobac/src/main/java/mobac/gui/MainGUI.java similarity index 67% rename from src/main/java/mobac/gui/MainGUI.java rename to mobac/src/main/java/mobac/gui/MainGUI.java index ab18e51..60c544f 100644 --- a/src/main/java/mobac/gui/MainGUI.java +++ b/mobac/src/main/java/mobac/gui/MainGUI.java @@ -1,73 +1,24 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Frame; -import java.awt.GraphicsEnvironment; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.Image; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.LinkedList; -import java.util.List; - -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.DefaultComboBoxModel; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JComboBox; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JLayeredPane; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JRadioButtonMenuItem; -import javax.swing.JScrollPane; -import javax.swing.JSlider; -import javax.swing.KeyStroke; -import javax.swing.SwingUtilities; -import javax.swing.UIManager; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.event.MenuEvent; -import javax.swing.event.MenuListener; -import javax.xml.bind.JAXBException; - +import ch.qos.logback.classic.Level; +import jakarta.xml.bind.JAXBException; +import mobac.exceptions.MapSourceInitializationException; import mobac.externaltools.ExternalToolDef; import mobac.externaltools.ExternalToolsLoader; import mobac.gui.actions.AddGpxTrackAreaPolygonMap; @@ -89,14 +40,17 @@ import mobac.gui.actions.RefreshCustomMapsources; import mobac.gui.actions.SelectionModeCircle; import mobac.gui.actions.SelectionModePolygon; import mobac.gui.actions.SelectionModeRectangle; +import mobac.gui.actions.SettingsButtonListener; import mobac.gui.actions.ShowAboutDialog; import mobac.gui.actions.ShowHelpAction; import mobac.gui.actions.ShowReadme; +import mobac.gui.actions.SplitPaneHideLeftComponent; import mobac.gui.atlastree.JAtlasTree; import mobac.gui.components.FilledLayeredPane; import mobac.gui.components.JAtlasNameField; import mobac.gui.components.JBookmarkMenuItem; import mobac.gui.components.JCollapsiblePanel; +import mobac.gui.components.JMapSourceTree; import mobac.gui.components.JMenuItem2; import mobac.gui.components.JZoomCheckBox; import mobac.gui.listeners.AtlasModelListener; @@ -111,14 +65,13 @@ import mobac.gui.mapview.controller.RectangleSelectionMapController; import mobac.gui.mapview.interfaces.MapEventListener; import mobac.gui.panels.JCoordinatesPanel; import mobac.gui.panels.JGpxPanel; +import mobac.gui.panels.JMapSourcesPanel; import mobac.gui.panels.JProfilesPanel; import mobac.gui.panels.JTileImageParametersPanel; import mobac.gui.panels.JTileStoreCoveragePanel; -import mobac.gui.settings.SettingsGUI; import mobac.mapsources.MapSourcesManager; import mobac.program.ProgramInfo; import mobac.program.interfaces.AtlasInterface; -import mobac.program.interfaces.FileBasedMapSource; import mobac.program.interfaces.InitializableMapSource; import mobac.program.interfaces.MapSource; import mobac.program.model.Bookmark; @@ -133,22 +86,82 @@ import mobac.utilities.GBC; import mobac.utilities.GUIExceptionHandler; import mobac.utilities.I18nUtils; import mobac.utilities.Utilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; +import javax.imageio.ImageIO; +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.ButtonGroup; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JLayeredPane; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JScrollPane; +import javax.swing.JSeparator; +import javax.swing.JSlider; +import javax.swing.JSplitPane; +import javax.swing.JTree; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GraphicsEnvironment; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.LinkedList; +import java.util.List; public class MainGUI extends JFrame implements MapEventListener { - private static final long serialVersionUID = 1L; - - private static Logger log = Logger.getLogger(MainGUI.class); - - private static Color labelBackgroundColor = new Color(0, 0, 0, 127); - private static Color checkboxBackgroundColor = new Color(0, 0, 0, 40); - private static Color labelForegroundColor = Color.WHITE; - - private static MainGUI mainGUI = null; + public static final int LEFT_PANEL_MIN_SIZE = 254; public static final ArrayList MOBAC_ICONS = new ArrayList(3); + private static final long serialVersionUID = 1L; + private static final int LEFT_PANEL_MARGIN = 2; + // MP: get custom font + private static final Color labelBackgroundColor = new Color(0, 0, 0, 127); + private static final Color checkboxBackgroundColor = new Color(0, 0, 0, 40); + private static final Color labelForegroundColor = Color.WHITE; + private static final Logger log = LoggerFactory.getLogger(MainGUI.class); + static Font sCustomFont = null; + private static MainGUI mainGUI = null; static { MOBAC_ICONS.add(Utilities.loadResourceImageIcon("mobac48.png").getImage()); @@ -156,42 +169,39 @@ public class MainGUI extends JFrame implements MapEventListener { MOBAC_ICONS.add(Utilities.loadResourceImageIcon("mobac16.png").getImage()); } - protected JMenuBar menuBar; - protected JMenu toolsMenu = null; - - private JMenu bookmarkMenu = null; - public final PreviewMap previewMap = new PreviewMap(); public final JAtlasTree jAtlasTree = new JAtlasTree(previewMap); - + private final AtlasCreate atlasCreateAction = new AtlasCreate(jAtlasTree); + private final JSplitPane splitPane; + private final JPanel mapControlPanel = new JPanel(new BorderLayout()); + private final JPanel leftPanel = new JPanel(new GridBagLayout()); + private final JPanel rightPanel = new JPanel(new GridBagLayout()); + public JCheckBox rulerCheckBox; + public JButton rulerButtonClear; + public JTileImageParametersPanel tileImageParametersPanel; + public JGpxPanel gpxPanel; + public JMenu logLevelMenu; + protected JMenuBar menuBar; + protected JMenu externalToolsMenu = null; + private JMenu bookmarkMenu = null; private JCheckBox wgsGridCheckBox; - private JComboBox wgsGridCombo; - + private JComboBox wgsGridCombo; private JLabel zoomLevelText; - private JComboBox gridZoomCombo; + private JComboBox gridZoomCombo; private JSlider zoomSlider; - private JComboBox mapSourceCombo; - private JButton settingsButton; + private JMapSourceTree mapSourceTree; private JAtlasNameField atlasNameTextField; private JButton createAtlasButton; private JPanel zoomLevelPanel; private JZoomCheckBox[] cbZoom = new JZoomCheckBox[0]; private JLabel amountOfTilesLabel; - - private AtlasCreate atlasCreateAction = new AtlasCreate(jAtlasTree); - + private JMapSourcesPanel mapSourcePanel; private JCoordinatesPanel coordinatesPanel; private JProfilesPanel profilesPanel; - public JTileImageParametersPanel tileImageParametersPanel; private JTileStoreCoveragePanel tileStoreCoveragePanel; - public JGpxPanel gpxPanel; - - private JPanel mapControlPanel = new JPanel(new BorderLayout()); - private JPanel leftPanel = new JPanel(new GridBagLayout()); private JPanel leftPanelContent = null; - private JPanel rightPanel = new JPanel(new GridBagLayout()); - - public JMenu logLevelMenu; + private JCollapsiblePanel zoomLevelsPanel; + private JCollapsiblePanel atlasContentPanel; private JMenuItem smRectangle; private JMenuItem smPolygon; private JMenuItem smCircle; @@ -199,9 +209,76 @@ public class MainGUI extends JFrame implements MapEventListener { private MercatorPixelCoordinate mapSelectionMax = null; private MercatorPixelCoordinate mapSelectionMin = null; + { + ImageIO.setUseCache(false); + } + + private MainGUI() { + super(); + mainGUI = this; + setIconImages(MOBAC_ICONS); + + GUIExceptionHandler.registerForCurrentThread(); + setTitle(ProgramInfo.getCompleteTitle()); + + log.trace("Creating main dialog - {}", getTitle()); + setResizable(true); + Dimension dScreen = Toolkit.getDefaultToolkit().getScreenSize(); + setMinimumSize(new Dimension(Math.min(800, dScreen.width), Math.min(590, dScreen.height))); + setSize(getMinimumSize()); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + addWindowListener(new WindowDestroyer()); + addComponentListener(new MainWindowListener()); + + previewMap.addMapEventListener(this); + + createControls(); + calculateNrOfTilesToDownload(); + setLayout(new BorderLayout()); + + // add(rightPanel, BorderLayout.EAST); + JLayeredPane layeredPane = new FilledLayeredPane(); + layeredPane.add(previewMap, Integer.valueOf(0)); + layeredPane.add(mapControlPanel, Integer.valueOf(1)); + // add(layeredPane, BorderLayout.CENTER); + + JPanel centerRightPanel = new JPanel(); + centerRightPanel.setLayout(new BorderLayout()); + centerRightPanel.add(layeredPane, BorderLayout.CENTER); + centerRightPanel.add(rightPanel, BorderLayout.EAST); + + leftPanel.setMinimumSize(new Dimension(LEFT_PANEL_MIN_SIZE, 100)); + splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, leftPanel, centerRightPanel); + splitPane.setOneTouchExpandable(true); + // splitPane.setDividerLocation(150); + add(splitPane); + + updateMapControlsPanel(); + updateLeftPanel(); + updateRightPanel(); + updateZoomLevelCheckBoxes(); + calculateNrOfTilesToDownload(); + + menuBar = new JMenuBar(); + prepareMenuBar(); + setJMenuBar(menuBar); + + loadSettings(); + profilesPanel.initialize(); + mapSourceChanged(previewMap.getMapSource()); + updateZoomLevelCheckBoxes(); + updateGridSizeCombo(); + tileImageParametersPanel.updateControlsState(); + zoomChanged(previewMap.getZoom()); + gridZoomChanged(previewMap.getGridZoom()); + previewMap.updateMapSelection(); + previewMap.grabFocus(); + } + public static void createMainGui() { - if (mainGUI != null) + if (mainGUI != null) { return; + } mainGUI = new MainGUI(); mainGUI.setVisible(true); @@ -212,9 +289,6 @@ public class MainGUI extends JFrame implements MapEventListener { return mainGUI; } - // MP: get custom font - static Font sCustomFont = null; - public static Font customFont() { if (sCustomFont == null) { // force to use Chinese font @@ -243,57 +317,6 @@ public class MainGUI extends JFrame implements MapEventListener { } } - private MainGUI() { - super(); - mainGUI = this; - setIconImages(MOBAC_ICONS); - - GUIExceptionHandler.registerForCurrentThread(); - setTitle(ProgramInfo.getCompleteTitle()); - - log.trace("Creating main dialog - " + getTitle()); - setResizable(true); - Dimension dScreen = Toolkit.getDefaultToolkit().getScreenSize(); - setMinimumSize(new Dimension(Math.min(800, dScreen.width), Math.min(590, dScreen.height))); - setSize(getMinimumSize()); - setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - addWindowListener(new WindowDestroyer()); - addComponentListener(new MainWindowListener()); - - previewMap.addMapEventListener(this); - - createControls(); - calculateNrOfTilesToDownload(); - setLayout(new BorderLayout()); - add(leftPanel, BorderLayout.WEST); - add(rightPanel, BorderLayout.EAST); - JLayeredPane layeredPane = new FilledLayeredPane(); - layeredPane.add(previewMap, Integer.valueOf(0)); - layeredPane.add(mapControlPanel, Integer.valueOf(1)); - add(layeredPane, BorderLayout.CENTER); - - updateMapControlsPanel(); - updateLeftPanel(); - updateRightPanel(); - updateZoomLevelCheckBoxes(); - calculateNrOfTilesToDownload(); - - menuBar = new JMenuBar(); - prepareMenuBar(); - setJMenuBar(menuBar); - - loadSettings(); - profilesPanel.initialize(); - mapSourceChanged(previewMap.getMapSource()); - updateZoomLevelCheckBoxes(); - updateGridSizeCombo(); - tileImageParametersPanel.updateControlsState(); - zoomChanged(previewMap.getZoom()); - gridZoomChanged(previewMap.getGridZoom()); - previewMap.updateMapSelection(); - previewMap.grabFocus(); - } - private void createControls() { // zoom slider @@ -312,7 +335,7 @@ public class MainGUI extends JFrame implements MapEventListener { zoomLevelText.setToolTipText(I18nUtils.localizedStringForKey("map_ctrl_zoom_level_title_tips")); // grid zoom combo - gridZoomCombo = new JComboBox(); + gridZoomCombo = new JComboBox<>(); gridZoomCombo.setEditable(false); gridZoomCombo.addActionListener(new GridZoomComboListener()); gridZoomCombo.setToolTipText(I18nUtils.localizedStringForKey("map_ctrl_zoom_grid_tips")); @@ -337,7 +360,7 @@ public class MainGUI extends JFrame implements MapEventListener { }); // WGS Grid combo - wgsGridCombo = new JComboBox(WgsDensity.values()); + wgsGridCombo = new JComboBox<>(WgsDensity.values()); wgsGridCombo.setMaximumRowCount(WgsDensity.values().length); wgsGridCombo.setVisible(s.enabled); wgsGridCombo.setSelectedItem(s.density); @@ -350,16 +373,52 @@ public class MainGUI extends JFrame implements MapEventListener { } }); - // map source combo - mapSourceCombo = new JComboBox(MapSourcesManager.getInstance().getEnabledOrderedMapSources()); - mapSourceCombo.setMaximumRowCount(20); - mapSourceCombo.addActionListener(new MapSourceComboListener()); - mapSourceCombo.setToolTipText(I18nUtils.localizedStringForKey("lp_map_source_combo_tips")); + // ruler. measuring tool + rulerCheckBox = new JCheckBox(); + rulerCheckBox.setVisible(true); + rulerCheckBox.setText(I18nUtils.localizedStringForKey("map_ctrl_ruler_title")); + rulerCheckBox.setToolTipText(I18nUtils.localizedStringForKey("map_ctrl_ruler_tooltip")); + rulerCheckBox.setOpaque(true); + rulerCheckBox.setBackground(checkboxBackgroundColor); + rulerCheckBox.setForeground(labelForegroundColor); + rulerCheckBox.setMargin(new Insets(0, 0, 0, 0)); + rulerCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + if (rulerCheckBox.isSelected()) { + previewMap.runRuler("start"); + rulerButtonClear.setVisible(previewMap.isMeasuring); + } else { + previewMap.runRuler("exit"); + rulerButtonClear.setVisible(false); + } + } + }); - // settings button - settingsButton = new JButton(I18nUtils.localizedStringForKey("lp_main_setting_button_title")); - settingsButton.addActionListener(new SettingsButtonListener()); - settingsButton.setToolTipText(I18nUtils.localizedStringForKey("lp_main_setting_button_tips")); + rulerButtonClear = new JButton(); + rulerButtonClear.setVisible(false); + rulerButtonClear.setText(I18nUtils.localizedStringForKey("map_ctrl_ruler_clear")); + rulerButtonClear.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + previewMap.runRuler("clear"); + } + }); + + // map source tree + mapSourceTree = new JMapSourceTree(MapSourcesManager.getInstance().getEnabledOrderedMapSources()); + mapSourceTree.addTreeSelectionListener(new MapSourceTreeListener()); + mapSourceTree.addMouseMotionListener(new MouseMotionAdapter() { + @Override + public void mouseMoved(MouseEvent e) { + boolean isLocationClickable = ((JMapSourceTree) e.getComponent()).isLocationClickable(e.getPoint()); + JTree jTree = (JTree) e.getComponent(); + // If a node is clickable, user will see a "hand" mouse cursor + jTree.setCursor(isLocationClickable + ? Cursor.getPredefinedCursor(Cursor.HAND_CURSOR) + : Cursor.getDefaultCursor()); + } + }); // atlas name text field atlasNameTextField = new JAtlasNameField(); @@ -369,6 +428,7 @@ public class MainGUI extends JFrame implements MapEventListener { // main button createAtlasButton = new JButton(I18nUtils.localizedStringForKey("lp_mian_create_btn_title")); + createAtlasButton.setIcon(new ImageIcon(MainGUI.class.getResource("/mobac/resources/images/atlas_create.png"))); createAtlasButton.addActionListener(atlasCreateAction); createAtlasButton.setToolTipText(I18nUtils.localizedStringForKey("lp_main_create_btn_tips")); @@ -394,96 +454,111 @@ public class MainGUI extends JFrame implements MapEventListener { private void prepareMenuBar() { // Atlas menu JMenu atlasMenu = new JMenu(I18nUtils.localizedStringForKey("menu_atlas")); + atlasMenu.setIcon(Utilities.loadResourceImageIcon("atlas.png")); atlasMenu.setMnemonic(KeyEvent.VK_A); JMenuItem newAtlas = new JMenuItem(I18nUtils.localizedStringForKey("menu_atlas_new")); + newAtlas.setIcon(Utilities.loadResourceImageIcon("atlas_add.png")); newAtlas.setMnemonic(KeyEvent.VK_N); newAtlas.addActionListener(new AtlasNew()); atlasMenu.add(newAtlas); JMenuItem convertAtlas = new JMenuItem(I18nUtils.localizedStringForKey("menu_atlas_convert_format")); + convertAtlas.setIcon(Utilities.loadResourceImageIcon("atlas_convert.png")); convertAtlas.setMnemonic(KeyEvent.VK_V); convertAtlas.addActionListener(new AtlasConvert()); atlasMenu.add(convertAtlas); atlasMenu.addSeparator(); JMenuItem createAtlas = new JMenuItem(I18nUtils.localizedStringForKey("menu_atlas_create")); + createAtlas.setIcon(Utilities.loadResourceImageIcon("atlas_create.png")); createAtlas.setMnemonic(KeyEvent.VK_C); createAtlas.addActionListener(atlasCreateAction); atlasMenu.add(createAtlas); - // Maps menu - JMenu mapsMenu = new JMenu(I18nUtils.localizedStringForKey("menu_maps")); - mapsMenu.setMnemonic(KeyEvent.VK_M); - JMenu selectionModeMenu = new JMenu(I18nUtils.localizedStringForKey("menu_maps_selection")); + // Selection menu - before, it was called "Maps menu" + JMenu selectionMenu = new JMenu(I18nUtils.localizedStringForKey("menu_selection")); + selectionMenu.setIcon(Utilities.loadResourceImageIcon("menu_icons/selections.png")); + selectionMenu.setMnemonic(KeyEvent.VK_S); + JMenu selectionModeMenu = new JMenu(I18nUtils.localizedStringForKey("menu_selection_selection")); + selectionModeMenu.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_selection_mode.png")); selectionModeMenu.setMnemonic(KeyEvent.VK_M); - mapsMenu.add(selectionModeMenu); + selectionMenu.add(selectionModeMenu); - smRectangle = new JRadioButtonMenuItem(I18nUtils.localizedStringForKey("menu_maps_selection_rect")); + smRectangle = new JCheckBoxMenuItem(I18nUtils.localizedStringForKey("menu_selection_selection_rect")); + smRectangle.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_selection_mode.png")); smRectangle.addActionListener(new SelectionModeRectangle()); smRectangle.setSelected(true); selectionModeMenu.add(smRectangle); - smPolygon = new JRadioButtonMenuItem(I18nUtils.localizedStringForKey("menu_maps_selection_polygon")); + smPolygon = new JCheckBoxMenuItem(I18nUtils.localizedStringForKey("menu_selection_selection_polygon")); + smPolygon.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_selection_polygon.png")); smPolygon.addActionListener(new SelectionModePolygon()); selectionModeMenu.add(smPolygon); - smCircle = new JRadioButtonMenuItem(I18nUtils.localizedStringForKey("menu_maps_selection_circle")); + smCircle = new JCheckBoxMenuItem(I18nUtils.localizedStringForKey("menu_selection_selection_circle")); + smCircle.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_selection_circle.png")); smCircle.addActionListener(new SelectionModeCircle()); selectionModeMenu.add(smCircle); - JMenuItem addSelection = new JMenuItem(I18nUtils.localizedStringForKey("menu_maps_selection_add")); + ButtonGroup selectionModeGroup = new ButtonGroup(); + selectionModeGroup.add(smRectangle); + selectionModeGroup.add(smPolygon); + selectionModeGroup.add(smCircle); + + JMenuItem addSelection = new JMenuItem(I18nUtils.localizedStringForKey("menu_selection_selection_add")); + addSelection.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_selection_add.png")); addSelection.addActionListener(AddMapLayer.INSTANCE); + + JSeparator selectionSeparator = new JSeparator(); + selectionMenu.add(selectionSeparator); addSelection.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.CTRL_MASK)); addSelection.setMnemonic(KeyEvent.VK_A); - mapsMenu.add(addSelection); + selectionMenu.add(addSelection); JMenuItem addGpxTrackSelection = new JMenuItem2( - I18nUtils.localizedStringForKey("menu_maps_selection_add_around_gpx"), AddGpxTrackPolygonMap.class); - mapsMenu.add(addGpxTrackSelection); + I18nUtils.localizedStringForKey("menu_selection_selection_add_around_gpx"), + AddGpxTrackPolygonMap.class); + addGpxTrackSelection.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_selection_add.png")); + selectionMenu.add(addGpxTrackSelection); JMenuItem addGpxTrackAreaSelection = new JMenuItem2( - I18nUtils.localizedStringForKey("menu_maps_selection_add_by_gpx"), + I18nUtils.localizedStringForKey("menu_selection_selection_add_by_gpx"), AddGpxTrackAreaPolygonMap.class); - mapsMenu.add(addGpxTrackAreaSelection); + addGpxTrackAreaSelection.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_selection_add.png")); + selectionMenu.add(addGpxTrackAreaSelection); // Bookmarks menu bookmarkMenu = new JMenu(I18nUtils.localizedStringForKey("menu_bookmark")); + bookmarkMenu.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_bookmarks.png")); bookmarkMenu.setMnemonic(KeyEvent.VK_B); JMenuItem addBookmark = new JMenuItem(I18nUtils.localizedStringForKey("menu_bookmark_save")); + addBookmark.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_save_view.png")); addBookmark.setMnemonic(KeyEvent.VK_S); addBookmark.addActionListener(new BookmarkAdd(previewMap)); bookmarkMenu.add(addBookmark); JMenuItem manageBookmarks = new JMenuItem2(I18nUtils.localizedStringForKey("menu_bookmark_manage"), BookmarkManage.class); + manageBookmarks.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_manage_bookmarks.png")); manageBookmarks.setMnemonic(KeyEvent.VK_S); bookmarkMenu.add(addBookmark); bookmarkMenu.add(manageBookmarks); bookmarkMenu.addSeparator(); - // Panels menu - JMenu panelsMenu = new JMenu(I18nUtils.localizedStringForKey("menu_panels")); - panelsMenu.setMnemonic(KeyEvent.VK_P); - JMenuItem showLeftPanel = new JMenuItem(I18nUtils.localizedStringForKey("menu_show_hide_left_panel")); - showLeftPanel.addActionListener(new PanelShowHide(leftPanel)); - JMenuItem showRightPanel = new JMenuItem(I18nUtils.localizedStringForKey("menu_show_hide_gpx_panel")); - showRightPanel.addActionListener(new PanelShowHide(rightPanel)); - panelsMenu.add(showLeftPanel); - panelsMenu.add(showRightPanel); - menuBar.add(atlasMenu); - menuBar.add(mapsMenu); + menuBar.add(selectionMenu); menuBar.add(bookmarkMenu); - menuBar.add(panelsMenu); - loadToolsMenu(); + loadExternalToolsMenu(); menuBar.add(Box.createHorizontalGlue()); // Debug menu JMenu debugMenu = new JMenu(I18nUtils.localizedStringForKey("menu_debug")); + debugMenu.setIcon(Utilities.loadResourceImageIcon("icon_debug_ms.png")); JMenuItem mapGrid = new JCheckBoxMenuItem(I18nUtils.localizedStringForKey("menu_debug_show_hide_tile_border"), false); + mapGrid.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_show_tile_borders.png")); mapGrid.addActionListener(new DebugShowMapTileGrid()); debugMenu.add(mapGrid); debugMenu.addSeparator(); @@ -491,24 +566,30 @@ public class MainGUI extends JFrame implements MapEventListener { debugMenu.setMnemonic(KeyEvent.VK_D); JMenuItem mapSourceNames = new JMenuItem2(I18nUtils.localizedStringForKey("menu_debug_show_all_map_source"), DebugShowMapSourceNames.class); + mapSourceNames.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_show_mapsources.png")); mapSourceNames.setMnemonic(KeyEvent.VK_N); debugMenu.add(mapSourceNames); debugMenu.addSeparator(); JMenuItem refreshCustomMapSources = new JMenuItem2( I18nUtils.localizedStringForKey("menu_debug_refresh_map_source"), RefreshCustomMapsources.class); + refreshCustomMapSources.setIcon(Utilities.loadResourceImageIcon("refresh.png")); debugMenu.add(refreshCustomMapSources); debugMenu.addSeparator(); JMenuItem showLog = new JMenuItem2(I18nUtils.localizedStringForKey("menu_debug_show_log_file"), DebugShowLogFile.class); + showLog.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_show_logfile.png")); showLog.setMnemonic(KeyEvent.VK_S); debugMenu.add(showLog); logLevelMenu = new JMenu(I18nUtils.localizedStringForKey("menu_debug_log_level")); + logLevelMenu.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_log_level.png")); logLevelMenu.setMnemonic(KeyEvent.VK_L); - Level[] list = new Level[] { Level.TRACE, Level.DEBUG, Level.INFO, Level.ERROR, Level.FATAL, Level.OFF }; + Level[] list = new Level[]{Level.TRACE, Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR, Level.OFF}; ActionListener al = new DebugSetLogLevel(); - Level rootLogLevel = Logger.getRootLogger().getLevel(); + ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory + .getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); + Level rootLogLevel = root.getLevel(); for (Level level : list) { String name = level.toString(); JRadioButtonMenuItem item = new JRadioButtonMenuItem(name, (rootLogLevel.toString().equals(name))); @@ -520,16 +601,50 @@ public class MainGUI extends JFrame implements MapEventListener { debugMenu.addSeparator(); JMenuItem report = new JMenuItem2(I18nUtils.localizedStringForKey("menu_debug_system_report"), DebugShowReport.class); + report.setIcon(Utilities.loadResourceImageIcon("menu_icons/menu_gen_sysreport.png")); report.setMnemonic(KeyEvent.VK_R); debugMenu.add(report); menuBar.add(debugMenu); + // Tools menu + JMenu toolsMenu = new JMenu(I18nUtils.localizedStringForKey("menu_tools")); + toolsMenu + .setIcon(new ImageIcon(MainGUI.class.getResource("/mobac/resources/images/menu_icons/menu_tools.png"))); + toolsMenu.setMnemonic(KeyEvent.VK_T); + menuBar.add(toolsMenu); + + JMenuItem settingsMenuItem = new JMenuItem2(I18nUtils.localizedStringForKey("menu_tools_settings"), + SettingsButtonListener.class); + settingsMenuItem.setIcon( + new ImageIcon(MainGUI.class.getResource("/mobac/resources/images/menu_icons/menu_settings.png"))); + toolsMenu.add(settingsMenuItem); + JSeparator separator = new JSeparator(); + toolsMenu.add(separator); + JMenuItem showRightPanel = new JMenuItem(I18nUtils.localizedStringForKey("menu_show_hide_gpx_panel")); + showRightPanel.setIcon( + new ImageIcon(MainGUI.class.getResource("/mobac/resources/images/menu_icons/menu_panels_right.png"))); + showRightPanel.addActionListener(new PanelShowHide(rightPanel)); + + JMenuItem showLeftPanel = new JMenuItem(I18nUtils.localizedStringForKey("menu_show_hide_left_panel")); + toolsMenu.add(showLeftPanel); + showLeftPanel.setIcon( + new ImageIcon(MainGUI.class.getResource("/mobac/resources/images/menu_icons/menu_panels_left.png"))); + + showLeftPanel.addActionListener(new SplitPaneHideLeftComponent(splitPane)); + toolsMenu.add(showRightPanel); + // Help menu JMenu help = new JMenu(I18nUtils.localizedStringForKey("menu_help")); + help.setIcon(new ImageIcon(MainGUI.class.getResource("/mobac/resources/images/menu_icons/menu_help.png"))); JMenuItem readme = new JMenuItem(I18nUtils.localizedStringForKey("menu_help_readme")); + readme.setIcon(new ImageIcon(MainGUI.class.getResource("/mobac/resources/images/menu_icons/menu_info.png"))); JMenuItem howToMap = new JMenuItem(I18nUtils.localizedStringForKey("menu_help_how_to_preview")); + howToMap.setIcon(new ImageIcon(MainGUI.class.getResource("/mobac/resources/images/menu_icons/menu_info.png"))); JMenuItem licenses = new JMenuItem(I18nUtils.localizedStringForKey("menu_help_licenses")); + licenses.setIcon( + new ImageIcon(MainGUI.class.getResource("/mobac/resources/images/menu_icons/menu_licenses.png"))); JMenuItem about = new JMenuItem(I18nUtils.localizedStringForKey("menu_help_about")); + about.setIcon(new ImageIcon(MainGUI.class.getResource("/mobac/resources/images/mobac16.png"))); readme.addActionListener(new ShowReadme()); about.addActionListener(new ShowAboutDialog()); howToMap.addActionListener(new ShowHelpAction()); @@ -544,15 +659,18 @@ public class MainGUI extends JFrame implements MapEventListener { menuBar.add(help); } - public void loadToolsMenu() { + public void loadExternalToolsMenu() { if (ExternalToolsLoader.load()) { - if (toolsMenu == null) { - toolsMenu = new JMenu(I18nUtils.localizedStringForKey("menu_tool")); - toolsMenu.addMenuListener(new MenuListener() { + if (externalToolsMenu == null) { + externalToolsMenu = new JMenu(I18nUtils.localizedStringForKey("menu_external_tools")); + externalToolsMenu.setIcon(new ImageIcon( + MainGUI.class.getResource("/mobac/resources/images/menu_icons/menu_external_tools.png"))); + externalToolsMenu.setMnemonic(KeyEvent.VK_E); + externalToolsMenu.addMenuListener(new MenuListener() { public void menuSelected(MenuEvent e) { - loadToolsMenu(); - log.debug("Tools menu Loaded"); + loadExternalToolsMenu(); + log.debug("External Tools menu Loaded"); } public void menuDeselected(MenuEvent e) { @@ -561,13 +679,15 @@ public class MainGUI extends JFrame implements MapEventListener { public void menuCanceled(MenuEvent e) { } }); - menuBar.add(toolsMenu); + menuBar.add(externalToolsMenu); } - toolsMenu.removeAll(); + externalToolsMenu.removeAll(); for (ExternalToolDef t : ExternalToolsLoader.tools) { - JMenuItem m = new JMenuItem(t.name); - m.addActionListener(t); - toolsMenu.add(m); + JMenuItem externalToolMenuItem = new JMenuItem(t.name); + externalToolMenuItem.addActionListener(t); + externalToolMenuItem.setIcon(new ImageIcon( + MainGUI.class.getResource("/mobac/resources/images/menu_icons/menu_external_tool_item.png"))); + externalToolsMenu.add(externalToolMenuItem); } } } @@ -577,25 +697,23 @@ public class MainGUI extends JFrame implements MapEventListener { coordinatesPanel.addButtonActionListener(new ApplySelectionButtonListener()); - JCollapsiblePanel mapSourcePanel = new JCollapsiblePanel( - I18nUtils.localizedStringForKey("lp_map_source_title"), new GridBagLayout()); - mapSourcePanel.addContent(mapSourceCombo, GBC.std().insets(2, 2, 2, 2).fill()); + mapSourcePanel = new JMapSourcesPanel(mapSourceTree); - JCollapsiblePanel zoomLevelsPanel = new JCollapsiblePanel(I18nUtils.localizedStringForKey("lp_zoom_title"), - new GridBagLayout()); + zoomLevelsPanel = new JCollapsiblePanel(I18nUtils.localizedStringForKey("lp_zoom_title"), new GridBagLayout()); zoomLevelsPanel.addContent(zoomLevelPanel, GBC.eol().insets(2, 4, 2, 0)); zoomLevelsPanel.addContent(amountOfTilesLabel, GBC.std().anchor(GBC.WEST).insets(0, 5, 0, 2)); - GBC gbc_std = GBC.std().insets(5, 2, 5, 3); - GBC gbc_eol = GBC.eol().insets(5, 2, 5, 3); + int leftPanelVerticalScrollWidth = 14; - JCollapsiblePanel atlasContentPanel = new JCollapsiblePanel(I18nUtils.localizedStringForKey("lp_atlas_title"), + GBC gbc_std = GBC.std().insets(5, 2, 5, 3); + GBC gbc_eol = GBC.eol().insets(LEFT_PANEL_MARGIN, 2, LEFT_PANEL_MARGIN, 3); + + atlasContentPanel = new JCollapsiblePanel(I18nUtils.localizedStringForKey("lp_atlas_title"), new GridBagLayout()); JScrollPane treeScrollPane = new JScrollPane(jAtlasTree, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); jAtlasTree.getTreeModel().addTreeModelListener(new AtlasModelListener(jAtlasTree, profilesPanel)); - treeScrollPane.setMinimumSize(new Dimension(100, 150)); treeScrollPane.setPreferredSize(new Dimension(100, 200)); treeScrollPane.setAutoscrolls(true); atlasContentPanel.addContent(treeScrollPane, GBC.eol().fill().insets(0, 1, 0, 0)); @@ -608,33 +726,23 @@ public class MainGUI extends JFrame implements MapEventListener { atlasContentPanel.addContent(new JLabel(I18nUtils.localizedStringForKey("lp_atlas_name_label_title")), gbc_std); atlasContentPanel.addContent(atlasNameTextField, gbc_eol.fill(GBC.HORIZONTAL)); - gbc_eol = GBC.eol().insets(5, 2, 5, 2).fill(GBC.HORIZONTAL); - leftPanelContent = new JPanel(new GridBagLayout()); - leftPanelContent.add(coordinatesPanel, gbc_eol); leftPanelContent.add(mapSourcePanel, gbc_eol); leftPanelContent.add(zoomLevelsPanel, gbc_eol); - leftPanelContent.add(tileImageParametersPanel, gbc_eol); leftPanelContent.add(atlasContentPanel, gbc_eol); - leftPanelContent.add(profilesPanel, gbc_eol); leftPanelContent.add(createAtlasButton, gbc_eol); - leftPanelContent.add(settingsButton, gbc_eol); + leftPanelContent.add(tileImageParametersPanel, gbc_eol); leftPanelContent.add(tileStoreCoveragePanel, gbc_eol); + leftPanelContent.add(coordinatesPanel, gbc_eol); leftPanelContent.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.VERTICAL)); JScrollPane scrollPane = new JScrollPane(leftPanelContent); scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); scrollPane.setBorder(BorderFactory.createEmptyBorder()); - // Set the scroll pane width large enough so that the - // scroll bar has enough space to appear right to it - Dimension d = scrollPane.getPreferredSize(); - d.width += 5 + scrollPane.getVerticalScrollBar().getWidth(); - // scrollPane.setPreferredSize(d); - scrollPane.setMinimumSize(d); + scrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(leftPanelVerticalScrollWidth, 0)); + leftPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.GRAY)); leftPanel.add(scrollPane, GBC.std().fill()); - // leftPanel.add(leftPanelContent, GBC.std().fill()); - } private void updateRightPanel() { @@ -662,6 +770,8 @@ public class MainGUI extends JFrame implements MapEventListener { topControls.add(gridZoomCombo, GBC.std().insets(10, 5, 0, 0)); topControls.add(wgsGridCheckBox, GBC.std().insets(10, 5, 0, 0)); topControls.add(wgsGridCombo, GBC.std().insets(5, 5, 0, 0)); + topControls.add(rulerCheckBox, GBC.std().insets(10, 5, 0, 0)); + topControls.add(rulerButtonClear, GBC.std().insets(10, 5, 0, 0)); topControls.add(Box.createHorizontalGlue(), GBC.std().fillH()); mapControlPanel.add(topControls, BorderLayout.NORTH); @@ -676,34 +786,48 @@ public class MainGUI extends JFrame implements MapEventListener { } public void updateMapSourcesList() { - MapSource ms = (MapSource) mapSourceCombo.getSelectedItem(); - mapSourceCombo - .setModel(new DefaultComboBoxModel(MapSourcesManager.getInstance().getEnabledOrderedMapSources())); - mapSourceCombo.setSelectedItem(ms); - MapSource ms2 = (MapSource) mapSourceCombo.getSelectedItem(); - if (!ms.equals(ms2)) + mapSourceTree.selectClickedMapSource(); + MapSource ms = mapSourceTree.getSelectedMapSource(); + mapSourceTree.initialize(MapSourcesManager.getInstance().getEnabledOrderedMapSources()); + if (!mapSourceTree.selectMapSource(ms)) { + mapSourceTree.selectFirstMapSource(); + } + MapSource ms2 = mapSourceTree.getSelectedMapSource(); + + if (!ms.equals(ms2)) { previewMap.setMapSource(ms2); + } } public void updateBookmarksMenu() { LinkedList items = new LinkedList(); for (int i = 0; i < bookmarkMenu.getMenuComponentCount(); i++) { JMenuItem item = bookmarkMenu.getItem(i); - if (!(item instanceof JBookmarkMenuItem)) + if (!(item instanceof JBookmarkMenuItem)) { items.add(item); + } } bookmarkMenu.removeAll(); for (JMenuItem item : items) { - if (item != null) + if (item != null) { bookmarkMenu.add(item); - else + } else { bookmarkMenu.addSeparator(); + } } - for (Bookmark b : Settings.getInstance().placeBookmarks) { - bookmarkMenu.add(new JBookmarkMenuItem(b)); + for (Bookmark bookmark : Settings.getInstance().placeBookmarks) { + JBookmarkMenuItem bookmarkMenuItem = new JBookmarkMenuItem(bookmark); + bookmarkMenuItem.setIcon(new ImageIcon( + MainGUI.class.getResource("/mobac/resources/images/menu_icons/menu_bookmark_item.png"))); + bookmarkMenu.add(bookmarkMenuItem); } } + public void setEnableLeftPanel(boolean enabled) { + zoomLevelsPanel.setVisible(enabled); + atlasContentPanel.setVisible(enabled); + } + private void loadSettings() { if (Profile.DEFAULT.exists()) { try { @@ -713,8 +837,9 @@ public class MainGUI extends JFrame implements MapEventListener { GUIExceptionHandler.processException(e); new AtlasNew().actionPerformed(null); } - } else + } else { new AtlasNew().actionPerformed(null); + } Settings settings = Settings.getInstance(); atlasNameTextField.setText(settings.elementName); @@ -733,6 +858,7 @@ public class MainGUI extends JFrame implements MapEventListener { } } } + coordinatesPanel.setNumberFormat(settings.coordinateNumberFormat); tileImageParametersPanel.loadSettings(); @@ -748,10 +874,12 @@ public class MainGUI extends JFrame implements MapEventListener { } else { setLocation(windowLocation); } - if (settings.mainWindow.maximized) + if (settings.mainWindow.maximized) { setExtendedState(Frame.MAXIMIZED_BOTH); + } leftPanel.setVisible(settings.mainWindow.leftPanelVisible); + leftPanel.setPreferredSize(new Dimension(settings.mainWindow.leftPanelWidth, 100)); rightPanel.setVisible(settings.mainWindow.rightPanelVisible); if (leftPanelContent != null) { @@ -759,8 +887,9 @@ public class MainGUI extends JFrame implements MapEventListener { if (c instanceof JCollapsiblePanel) { JCollapsiblePanel cp = (JCollapsiblePanel) c; String name = cp.getName(); - if (name != null && settings.mainWindow.collapsedPanels.contains(name)) + if (name != null && settings.mainWindow.collapsedPanels.contains(name)) { cp.setCollapsed(true); + } } } } @@ -792,12 +921,14 @@ public class MainGUI extends JFrame implements MapEventListener { for (Component c : leftPanelContent.getComponents()) { if (c instanceof JCollapsiblePanel) { JCollapsiblePanel cp = (JCollapsiblePanel) c; - if (cp.isCollapsed()) + if (cp.isCollapsed()) { s.mainWindow.collapsedPanels.add(cp.getName()); + } } } } s.mainWindow.leftPanelVisible = leftPanel.isVisible(); + s.mainWindow.leftPanelWidth = leftPanel.getWidth(); s.mainWindow.rightPanelVisible = rightPanel.isVisible(); checkAndSaveSettings(); } catch (Exception e) { @@ -813,8 +944,9 @@ public class MainGUI extends JFrame implements MapEventListener { I18nUtils.localizedStringForKey("msg_setting_file_is_changed_by_other"), I18nUtils.localizedStringForKey("msg_setting_file_is_changed_by_other_title"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - if (x != JOptionPane.YES_OPTION) + if (x != JOptionPane.YES_OPTION) { return; + } } Settings.save(); @@ -832,26 +964,6 @@ public class MainGUI extends JFrame implements MapEventListener { previewMap.refreshMap(); } - private class ZoomSliderListener implements ChangeListener { - public void stateChanged(ChangeEvent e) { - previewMap.setZoom(zoomSlider.getValue()); - } - } - - private class GridZoomComboListener implements ActionListener { - public void actionPerformed(ActionEvent e) { - if (!gridZoomCombo.isEnabled()) - return; - GridZoom g = (GridZoom) gridZoomCombo.getSelectedItem(); - if (g == null) - return; - log.debug("Selected grid zoom combo box item has changed: " + g.getZoom()); - previewMap.setGridZoom(g.getZoom()); - repaint(); - previewMap.updateMapSelection(); - } - } - private void updateGridSizeCombo() { int maxZoom = previewMap.getMapSource().getMaxZoom(); int minZoom = previewMap.getMapSource().getMinZoom(); @@ -870,63 +982,21 @@ public class MainGUI extends JFrame implements MapEventListener { for (int i = maxZoom; i >= minZoom; i--) { gridZoomCombo.addItem(new GridZoom(i)); } - if (lastGridZoom != null) + if (lastGridZoom != null) { gridZoomCombo.setSelectedItem(lastGridZoom); + } gridZoomCombo.setEnabled(true); } - private class ApplySelectionButtonListener implements ActionListener { - public void actionPerformed(ActionEvent e) { - setSelectionByEnteredCoordinates(); - } - } - - private class MapSourceComboListener implements ActionListener { - public void actionPerformed(ActionEvent e) { - MapSource mapSource = (MapSource) mapSourceCombo.getSelectedItem(); - if (mapSource == null) { - mapSourceCombo.setSelectedIndex(0); - mapSource = (MapSource) mapSourceCombo.getSelectedItem(); - } - if (mapSource instanceof InitializableMapSource) - // initialize the map source e.g. detect available zoom levels - ((InitializableMapSource) mapSource).initialize(); - previewMap.setMapSource(mapSource); - zoomSlider.setMinimum(previewMap.getMapSource().getMinZoom()); - zoomSlider.setMaximum(previewMap.getMapSource().getMaxZoom()); - updateGridSizeCombo(); - updateZoomLevelCheckBoxes(); - calculateNrOfTilesToDownload(); - } - } - - private class LoadProfileListener implements ActionListener { - public void actionPerformed(ActionEvent e) { - Profile profile = profilesPanel.getSelectedProfile(); - profilesPanel.getDeleteButton().setEnabled(profile != null); - if (profile == null) - return; - - jAtlasTree.load(profile); - previewMap.repaint(); - tileImageParametersPanel.atlasFormatChanged(jAtlasTree.getAtlas().getOutputFormat()); - } - } - - private class SettingsButtonListener implements ActionListener { - public void actionPerformed(ActionEvent e) { - SettingsGUI.showSettingsDialog(MainGUI.this); - } - } - private void updateZoomLevelCheckBoxes() { MapSource tileSource = previewMap.getMapSource(); int zoomLevels = tileSource.getMaxZoom() - tileSource.getMinZoom() + 1; zoomLevels = Math.max(zoomLevels, 0); - JCheckBox oldZoomLevelCheckBoxes[] = cbZoom; + JCheckBox[] oldZoomLevelCheckBoxes = cbZoom; int oldMinZoom = 0; - if (cbZoom.length > 0) + if (cbZoom.length > 0) { oldMinZoom = cbZoom[0].getZoomLevel(); + } cbZoom = new JZoomCheckBox[zoomLevels]; zoomLevelPanel.removeAll(); @@ -942,8 +1012,9 @@ public class MainGUI extends JFrame implements MapEventListener { cb.setFocusable(false); cb.setName(Integer.toString(cbz)); int oldCbIndex = cbz - oldMinZoom; - if (oldCbIndex >= 0 && oldCbIndex < (oldZoomLevelCheckBoxes.length)) + if (oldCbIndex >= 0 && oldCbIndex < (oldZoomLevelCheckBoxes.length)) { cb.setSelected(oldZoomLevelCheckBoxes[oldCbIndex].isSelected()); + } cb.addActionListener(cbl); // cb.setToolTipText("Select zoom level " + cbz + " for atlas"); zoomLevelPanel.add(cb); @@ -956,12 +1027,6 @@ public class MainGUI extends JFrame implements MapEventListener { amountOfTilesLabel.setForeground(Color.black); } - private class ZoomLevelCheckBoxListener implements ActionListener { - public void actionPerformed(ActionEvent e) { - calculateNrOfTilesToDownload(); - } - } - public void selectionChanged(MercatorPixelCoordinate max, MercatorPixelCoordinate min) { mapSelectionMax = max; mapSelectionMin = min; @@ -979,7 +1044,8 @@ public class MainGUI extends JFrame implements MapEventListener { } public MapSource getSelectedMapSource() { - return (MapSource) mapSourceCombo.getSelectedItem(); + mapSourceTree.selectClickedMapSource(); + return mapSourceTree.getSelectedMapSource(); } public SelectedZoomLevels getSelectedZoomLevels() { @@ -987,39 +1053,42 @@ public class MainGUI extends JFrame implements MapEventListener { } public void selectNextMapSource() { - if (mapSourceCombo.getSelectedIndex() == mapSourceCombo.getItemCount() - 1) { + if (!mapSourceTree.selectNextMapSource()) { Toolkit.getDefaultToolkit().beep(); } else { - mapSourceCombo.setSelectedIndex(mapSourceCombo.getSelectedIndex() + 1); + mapSourceChanged(mapSourceTree.getSelectedMapSource()); } } public void selectPreviousMapSource() { - if (mapSourceCombo.getSelectedIndex() == 0) { + if (!mapSourceTree.selectPreviousMapSource()) { Toolkit.getDefaultToolkit().beep(); } else { - mapSourceCombo.setSelectedIndex(mapSourceCombo.getSelectedIndex() - 1); + mapSourceChanged(mapSourceTree.getSelectedMapSource()); } } public void mapSourceChanged(MapSource newMapSource) { // TODO update selected area if new map source has different projectionCategory calculateNrOfTilesToDownload(); - // if (newMapSource != null && newMapSource.equals(mapSourceCombo.getSelectedItem())) + // if (newMapSource != null && + // newMapSource.equals(mapSourceCombo.getSelectedItem())) // return; - mapSourceCombo.setSelectedItem(newMapSource); + mapSourceTree.selectMapSource(newMapSource); + mapSourcePanel.setMapSourceLabel(newMapSource); } public void mapSelectionControllerChanged(JMapController newMapController) { smPolygon.setSelected(false); smCircle.setSelected(false); smRectangle.setSelected(false); - if (newMapController instanceof PolygonSelectionMapController) + if (newMapController instanceof PolygonSelectionMapController) { smPolygon.setSelected(true); - else if (newMapController instanceof PolygonCircleSelectionMapController) + } else if (newMapController instanceof PolygonCircleSelectionMapController) { smCircle.setSelected(true); - else if (newMapController instanceof RectangleSelectionMapController) + } else if (newMapController instanceof RectangleSelectionMapController) { smRectangle.setSelected(true); + } } private void setSelectionByEnteredCoordinates() { @@ -1031,8 +1100,9 @@ public class MainGUI extends JFrame implements MapEventListener { } public MapSelection getMapSelectionCoordinates() { - if (mapSelectionMax == null || mapSelectionMin == null) + if (mapSelectionMax == null || mapSelectionMin == null) { return null; + } return new MapSelection(previewMap.getMapSource(), mapSelectionMax, mapSelectionMin); } @@ -1063,11 +1133,12 @@ public class MainGUI extends JFrame implements MapEventListener { totalNrOfTiles += info[0]; hint.append(String.format(I18nUtils.localizedStringForKey("lp_zoom_total_tile_hint_row"), zoomLevels[i], info[0], info[1], info[2])); - // hint.append("
Level " + zoomLevels[i] + ": " + info[0] + " (" + info[1] + "*" + info[2] + + // hint.append("
Level " + zoomLevels[i] + ": " + info[0] + " (" + info[1] + + // "*" + info[2] + // ")"); } - String hintText = "" + hint.toString() + ""; - amountOfTilesLabel.setText(String.format(baseText, Long.toString(totalNrOfTiles))); + String hintText = "" + hint + ""; + amountOfTilesLabel.setText(String.format(baseText, totalNrOfTiles)); amountOfTilesLabel.setToolTipText(hintText); } catch (Exception e) { amountOfTilesLabel.setText(String.format(baseText, "?")); @@ -1080,6 +1151,87 @@ public class MainGUI extends JFrame implements MapEventListener { return jAtlasTree.getAtlas(); } + private class ZoomSliderListener implements ChangeListener { + public void stateChanged(ChangeEvent e) { + previewMap.setZoom(zoomSlider.getValue()); + } + } + + private class GridZoomComboListener implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (!gridZoomCombo.isEnabled()) { + return; + } + GridZoom g = (GridZoom) gridZoomCombo.getSelectedItem(); + if (g == null) { + return; + } + log.debug("Selected grid zoom combo box item has changed: " + g.getZoom()); + previewMap.setGridZoom(g.getZoom()); + repaint(); + previewMap.updateMapSelection(); + } + } + + private class ApplySelectionButtonListener implements ActionListener { + public void actionPerformed(ActionEvent e) { + setSelectionByEnteredCoordinates(); + } + } + + private class MapSourceTreeListener implements TreeSelectionListener { + + @Override + public void valueChanged(TreeSelectionEvent e) { + mapSourceTree.selectClickedMapSource(); + MapSource selectedMapSource = mapSourceTree.getSelectedMapSource(); + if (selectedMapSource == null) { + boolean wasFirstValidSourceSelected = mapSourceTree.selectFirstMapSource(); + if (!wasFirstValidSourceSelected) { + return; + } + selectedMapSource = mapSourceTree.getSelectedMapSource(); + } + if (selectedMapSource instanceof InitializableMapSource) { + // initialize the map source e.g. detect available zoom levels + try { + ((InitializableMapSource) selectedMapSource).initialize(); + } catch (MapSourceInitializationException e1) { + JOptionPane.showMessageDialog(null, + I18nUtils.localizedStringForKey("msg_map_source_initialization_failed", + selectedMapSource.toString(), e1.getLocalizedMessage()), + I18nUtils.localizedStringForKey("Error"), JOptionPane.ERROR_MESSAGE); + } + } + previewMap.setMapSource(selectedMapSource); + zoomSlider.setMinimum(previewMap.getMapSource().getMinZoom()); + zoomSlider.setMaximum(previewMap.getMapSource().getMaxZoom()); + updateGridSizeCombo(); + updateZoomLevelCheckBoxes(); + calculateNrOfTilesToDownload(); + } + } + + private class LoadProfileListener implements ActionListener { + public void actionPerformed(ActionEvent e) { + Profile profile = profilesPanel.getSelectedProfile(); + profilesPanel.getDeleteButton().setEnabled(profile != null); + if (profile == null) { + return; + } + + jAtlasTree.load(profile); + previewMap.repaint(); + tileImageParametersPanel.atlasFormatChanged(jAtlasTree.getAtlas().getOutputFormat()); + } + } + + private class ZoomLevelCheckBoxListener implements ActionListener { + public void actionPerformed(ActionEvent e) { + calculateNrOfTilesToDownload(); + } + } + private class WindowDestroyer extends WindowAdapter { @Override @@ -1097,9 +1249,10 @@ public class MainGUI extends JFrame implements MapEventListener { } /** - * Saves the window position and size when window is moved or resized. This is necessary because of the maximized - * state. If a window is maximized it is impossible to retrieve the window size & position of the non-maximized - * window - therefore we have to collect the information every time they change. + * Saves the window position and size when window is moved or resized. This is + * necessary because of the maximized state. If a window is maximized it is + * impossible to retrieve the window size & position of the non-maximized window + * - therefore we have to collect the information every time they change. */ private class MainWindowListener extends ComponentAdapter { public void componentResized(ComponentEvent event) { @@ -1117,12 +1270,12 @@ public class MainGUI extends JFrame implements MapEventListener { // Note(Java bug): Sometimes getExtendedState() says the window is // not maximized but maximizing is already in progress and therefore // the window bounds are already changed. - if ((getExtendedState() & MAXIMIZED_BOTH) != 0) + if ((getExtendedState() & MAXIMIZED_BOTH) != 0) { return; + } Settings s = Settings.getInstance(); s.mainWindow.size = getSize(); s.mainWindow.position = getLocation(); } } - } diff --git a/src/main/java/mobac/gui/SplashFrame.java b/mobac/src/main/java/mobac/gui/SplashFrame.java similarity index 88% rename from src/main/java/mobac/gui/SplashFrame.java rename to mobac/src/main/java/mobac/gui/SplashFrame.java index 147f2c2..adcb984 100644 --- a/src/main/java/mobac/gui/SplashFrame.java +++ b/mobac/src/main/java/mobac/gui/SplashFrame.java @@ -1,41 +1,36 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui; -import java.awt.Dimension; -import java.awt.HeadlessException; -import java.awt.Toolkit; +import mobac.utilities.Utilities; import javax.swing.BorderFactory; import javax.swing.JFrame; import javax.swing.JLabel; - -import mobac.utilities.Utilities; +import java.awt.Dimension; +import java.awt.HeadlessException; +import java.awt.Toolkit; public class SplashFrame extends JFrame { private static SplashFrame startupFrame; - public static void showFrame() { - startupFrame = new SplashFrame(); - } - public SplashFrame() throws HeadlessException { - //super(MainGUI.localizedStringForKey("splash_title")); + // super(MainGUI.localizedStringForKey("splash_title")); super("MOBAC"); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); setUndecorated(true); @@ -51,9 +46,14 @@ public class SplashFrame extends JFrame { setVisible(true); } + public static void showFrame() { + startupFrame = new SplashFrame(); + } + public static void hideFrame() { - if (startupFrame == null) + if (startupFrame == null) { return; + } startupFrame.setVisible(false); startupFrame.dispose(); startupFrame = null; diff --git a/src/main/java/mobac/gui/actions/AddGpxTrackAreaPolygonMap.java b/mobac/src/main/java/mobac/gui/actions/AddGpxTrackAreaPolygonMap.java similarity index 88% rename from src/main/java/mobac/gui/actions/AddGpxTrackAreaPolygonMap.java rename to mobac/src/main/java/mobac/gui/actions/AddGpxTrackAreaPolygonMap.java index d289617..5ff47bb 100644 --- a/src/main/java/mobac/gui/actions/AddGpxTrackAreaPolygonMap.java +++ b/mobac/src/main/java/mobac/gui/actions/AddGpxTrackAreaPolygonMap.java @@ -1,28 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.Polygon; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; - -import javax.swing.JOptionPane; - import mobac.data.gpx.gpx11.TrkType; import mobac.data.gpx.gpx11.TrksegType; import mobac.data.gpx.interfaces.GpxPoint; @@ -45,6 +38,12 @@ import mobac.program.model.Settings; import mobac.program.model.TileImageParameters; import mobac.utilities.I18nUtils; +import javax.swing.JOptionPane; +import java.awt.Polygon; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + public class AddGpxTrackAreaPolygonMap implements ActionListener { public static final AddGpxTrackAreaPolygonMap INSTANCE = new AddGpxTrackAreaPolygonMap(); @@ -53,8 +52,9 @@ public class AddGpxTrackAreaPolygonMap implements ActionListener { MainGUI mg = MainGUI.getMainGUI(); GpxEntry entry = mg.gpxPanel.getSelectedEntry(); - if (entry == null) + if (entry == null) { return; + } TrksegType trk = null; TrkType t = null; @@ -64,21 +64,24 @@ public class AddGpxTrackAreaPolygonMap implements ActionListener { GpxRootEntry re = (GpxRootEntry) entry; List tlist = re.getLayer().getGpx().getTrk(); if (tlist.size() > 1) { - JOptionPane - .showMessageDialog(mg, I18nUtils.localizedStringForKey("msg_add_gpx_polygon_too_many_track")); + JOptionPane.showMessageDialog(mg, + I18nUtils.localizedStringForKey("msg_add_gpx_polygon_too_many_track")); return; - } else if (tlist.size() == 1) + } else if (tlist.size() == 1) { t = tlist.get(0); + } } - if (entry instanceof TrkEntry) + if (entry instanceof TrkEntry) { t = ((TrkEntry) entry).getTrk(); + } if (t != null) { if (t.getTrkseg().size() > 1) { JOptionPane.showMessageDialog(mg, I18nUtils.localizedStringForKey("msg_add_gpx_polygon_too_many_segment")); return; - } else if (t.getTrkseg().size() == 1) + } else if (t.getTrkseg().size() == 1) { trk = t.getTrkseg().get(0); + } } if (trk == null) { JOptionPane.showMessageDialog(mg, I18nUtils.localizedStringForKey("msg_add_gpx_polygon_no_select"), @@ -103,8 +106,8 @@ public class AddGpxTrackAreaPolygonMap implements ActionListener { EastNorthCoordinate maxCoordinate = new EastNorthCoordinate(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY); for (int i = 0; i < trackPoints.length; i++) { GpxPoint gpxPoint = points.get(i); - EastNorthCoordinate c = new EastNorthCoordinate(gpxPoint.getLat().doubleValue(), gpxPoint.getLon() - .doubleValue()); + EastNorthCoordinate c = new EastNorthCoordinate(gpxPoint.getLat().doubleValue(), + gpxPoint.getLon().doubleValue()); minCoordinate.lat = Math.min(minCoordinate.lat, c.lat); minCoordinate.lon = Math.min(minCoordinate.lon, c.lon); maxCoordinate.lat = Math.max(maxCoordinate.lat, c.lat); @@ -124,7 +127,7 @@ public class AddGpxTrackAreaPolygonMap implements ActionListener { layer = new Layer(atlasInterface, layerName); success = true; } catch (InvalidNameException e) { - layerName = name + "_" + Integer.toString(c++); + layerName = name + "_" + c++; } } while (!success); @@ -148,12 +151,13 @@ public class AddGpxTrackAreaPolygonMap implements ActionListener { int result = JOptionPane.showConfirmDialog(mg, msg, I18nUtils.localizedStringForKey("msg_add_gpx_polygon_maxsize_title"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - if (result != JOptionPane.YES_OPTION) + if (result != JOptionPane.YES_OPTION) { return; + } } for (int zoom : zoomLevels) { - String mapName = String.format(mapNameFmt, new Object[] { layerName, zoom }); + String mapName = String.format(mapNameFmt, layerName, zoom); MapInterface map = MapPolygon.createFromMapPolygon(layer, mapName, zoom, maxZoomMap); layer.addMap(map); } diff --git a/src/main/java/mobac/gui/actions/AddGpxTrackPolygonMap.java b/mobac/src/main/java/mobac/gui/actions/AddGpxTrackPolygonMap.java similarity index 84% rename from src/main/java/mobac/gui/actions/AddGpxTrackPolygonMap.java rename to mobac/src/main/java/mobac/gui/actions/AddGpxTrackPolygonMap.java index 28df13c..1d59ebd 100644 --- a/src/main/java/mobac/gui/actions/AddGpxTrackPolygonMap.java +++ b/mobac/src/main/java/mobac/gui/actions/AddGpxTrackPolygonMap.java @@ -1,35 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.Point; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; - -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - import mobac.data.gpx.gpx11.TrkType; import mobac.data.gpx.gpx11.TrksegType; import mobac.data.gpx.interfaces.GpxPoint; @@ -55,9 +41,20 @@ import mobac.program.model.TileImageParameters; import mobac.program.model.UnitSystem; import mobac.utilities.I18nUtils; -public class AddGpxTrackPolygonMap implements ActionListener { +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; - public static final AddGpxTrackPolygonMap INSTANCE = new AddGpxTrackPolygonMap(); +public class AddGpxTrackPolygonMap implements ActionListener { private MapAreaHighlightingLayer msl = null; @@ -65,8 +62,9 @@ public class AddGpxTrackPolygonMap implements ActionListener { final MainGUI mg = MainGUI.getMainGUI(); GpxEntry entry = mg.gpxPanel.getSelectedEntry(); - if (entry == null) + if (entry == null) { return; + } TrksegType trk = null; TrkType t = null; @@ -76,21 +74,24 @@ public class AddGpxTrackPolygonMap implements ActionListener { GpxRootEntry re = (GpxRootEntry) entry; List tlist = re.getLayer().getGpx().getTrk(); if (tlist.size() > 1) { - JOptionPane - .showMessageDialog(mg, I18nUtils.localizedStringForKey("msg_add_gpx_polygon_too_many_track")); + JOptionPane.showMessageDialog(mg, + I18nUtils.localizedStringForKey("msg_add_gpx_polygon_too_many_track")); return; - } else if (tlist.size() == 1) + } else if (tlist.size() == 1) { t = tlist.get(0); + } } - if (entry instanceof TrkEntry) + if (entry instanceof TrkEntry) { t = ((TrkEntry) entry).getTrk(); + } if (t != null) { if (t.getTrkseg().size() > 1) { JOptionPane.showMessageDialog(mg, I18nUtils.localizedStringForKey("msg_add_gpx_polygon_too_many_segment")); return; - } else if (t.getTrkseg().size() == 1) + } else if (t.getTrkseg().size() == 1) { trk = t.getTrkseg().get(0); + } } if (trk == null) { JOptionPane.showMessageDialog(mg, I18nUtils.localizedStringForKey("msg_add_gpx_polygon_no_select"), @@ -115,8 +116,8 @@ public class AddGpxTrackPolygonMap implements ActionListener { EastNorthCoordinate maxCoordinate = new EastNorthCoordinate(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY); for (int i = 0; i < trackPoints.length; i++) { GpxPoint gpxPoint = points.get(i); - EastNorthCoordinate c = new EastNorthCoordinate(gpxPoint.getLat().doubleValue(), gpxPoint.getLon() - .doubleValue()); + EastNorthCoordinate c = new EastNorthCoordinate(gpxPoint.getLat().doubleValue(), + gpxPoint.getLon().doubleValue()); minCoordinate.lat = Math.min(minCoordinate.lat, c.lat); minCoordinate.lon = Math.min(minCoordinate.lon, c.lon); maxCoordinate.lat = Math.max(maxCoordinate.lat, c.lat); @@ -150,23 +151,22 @@ public class AddGpxTrackPolygonMap implements ActionListener { d /= unitSystem.unitFactor; unitName = unitSystem.unitLarge; } - label.setText(String.format(I18nUtils.localizedStringForKey("dlg_gpx_track_select_distance"), - ((int) d), unitName)); + label.setText(String.format(I18nUtils.localizedStringForKey("dlg_gpx_track_select_distance"), ((int) d), + unitName)); } }; final JButton previewButton = new JButton(I18nUtils.localizedStringForKey("dlg_gpx_track_select_preview")); - previewButton.addActionListener(new ActionListener() { - - @Override - public void actionPerformed(ActionEvent e) { - int distance = slider.getValue(); - MapPolygon maxZoomMap = MapPolygon.createTrackEnclosure(null, "Dummy", mapSource, maxZoom, trackPoints, - distance, customTileParameters); - if (msl != null) - msl.setObject(maxZoomMap); + previewButton.addActionListener(e -> { + int distance = slider.getValue(); + MapPolygon maxZoomMap = MapPolygon.createTrackEnclosure(null, "Dummy", mapSource, maxZoom, trackPoints, + distance, customTileParameters); + if (msl == null) { msl = new MapAreaHighlightingLayer(maxZoomMap); - mg.previewMap.repaint(); + mg.previewMap.mapLayers.add(msl); + } else { + msl.setObject(maxZoomMap); } + mg.previewMap.repaint(); }); cl.stateChanged(null); @@ -183,8 +183,9 @@ public class AddGpxTrackPolygonMap implements ActionListener { msl.setObject(null); } - if (result != JOptionPane.OK_OPTION) + if (result != JOptionPane.OK_OPTION) { return; + } int distance = slider.getValue(); MapPolygon maxZoomMap = MapPolygon.createTrackEnclosure(null, "Dummy", mapSource, maxZoom, trackPoints, @@ -199,7 +200,7 @@ public class AddGpxTrackPolygonMap implements ActionListener { layer = new Layer(atlasInterface, layerName); success = true; } catch (InvalidNameException e) { - layerName = name + "_" + Integer.toString(c++); + layerName = name + "_" + c++; } } while (!success); @@ -210,12 +211,13 @@ public class AddGpxTrackPolygonMap implements ActionListener { result = JOptionPane.showConfirmDialog(mg, msg, I18nUtils.localizedStringForKey("msg_add_gpx_polygon_maxsize_title"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - if (result != JOptionPane.YES_OPTION) + if (result != JOptionPane.YES_OPTION) { return; + } } for (int zoom : zoomLevels) { - String mapName = String.format(mapNameFmt, new Object[] { layerName, zoom }); + String mapName = String.format(mapNameFmt, layerName, zoom); MapInterface map = MapPolygon.createFromMapPolygon(layer, mapName, zoom, maxZoomMap); layer.addMap(map); } diff --git a/src/main/java/mobac/gui/actions/AddMapLayer.java b/mobac/src/main/java/mobac/gui/actions/AddMapLayer.java similarity index 85% rename from src/main/java/mobac/gui/actions/AddMapLayer.java rename to mobac/src/main/java/mobac/gui/actions/AddMapLayer.java index 7a2f744..bde2c49 100644 --- a/src/main/java/mobac/gui/actions/AddMapLayer.java +++ b/mobac/src/main/java/mobac/gui/actions/AddMapLayer.java @@ -1,40 +1,41 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - import mobac.gui.MainGUI; import mobac.gui.mapview.controller.AbstractPolygonSelectionMapController; import mobac.gui.mapview.controller.JMapController; import mobac.gui.mapview.controller.RectangleSelectionMapController; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + public class AddMapLayer implements ActionListener { public static final AddMapLayer INSTANCE = new AddMapLayer(); public void actionPerformed(ActionEvent event) { JMapController msc = MainGUI.getMainGUI().previewMap.getMapSelectionController(); - if (msc instanceof RectangleSelectionMapController) + if (msc instanceof RectangleSelectionMapController) { new AddRectangleMapAutocut().actionPerformed(event); - else if (msc instanceof AbstractPolygonSelectionMapController) + } else if (msc instanceof AbstractPolygonSelectionMapController) { new AddPolygonMapLayer().actionPerformed(event); - else + } else { throw new RuntimeException("Unknown mapSelectionController type"); + } } } diff --git a/src/main/java/mobac/gui/actions/AddPolygonMapLayer.java b/mobac/src/main/java/mobac/gui/actions/AddPolygonMapLayer.java similarity index 88% rename from src/main/java/mobac/gui/actions/AddPolygonMapLayer.java rename to mobac/src/main/java/mobac/gui/actions/AddPolygonMapLayer.java index 0db2428..04bce53 100644 --- a/src/main/java/mobac/gui/actions/AddPolygonMapLayer.java +++ b/mobac/src/main/java/mobac/gui/actions/AddPolygonMapLayer.java @@ -1,29 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.Point; -import java.awt.Polygon; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.List; - -import javax.swing.JOptionPane; - import mobac.exceptions.InvalidNameException; import mobac.gui.MainGUI; import mobac.gui.atlastree.JAtlasTree; @@ -38,6 +30,13 @@ import mobac.program.model.SelectedZoomLevels; import mobac.program.model.TileImageParameters; import mobac.utilities.I18nUtils; +import javax.swing.JOptionPane; +import java.awt.Point; +import java.awt.Polygon; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + public class AddPolygonMapLayer implements ActionListener { public void actionPerformed(ActionEvent event) { @@ -69,14 +68,14 @@ public class AddPolygonMapLayer implements ActionListener { layer = new Layer(atlasInterface, layerName); success = true; } catch (InvalidNameException e) { - layerName = name + "_" + Integer.toString(c++); + layerName = name + "_" + c++; } } while (!success); List polygonPoints = msc.getPolygonPoints(); for (int zoom : zoomLevels) { - int xpoints[] = new int[polygonPoints.size()]; - int ypoints[] = new int[polygonPoints.size()]; + int[] xpoints = new int[polygonPoints.size()]; + int[] ypoints = new int[polygonPoints.size()]; for (int i = 0; i < xpoints.length; i++) { Point p = mapSpace.changeZoom(polygonPoints.get(i), JMapViewer.MAX_ZOOM, zoom); @@ -89,7 +88,7 @@ public class AddPolygonMapLayer implements ActionListener { // int maxMapSize = Settings.getInstance().maxMapSize; // System.out.println(bounds.height + " " + bounds.width); - String mapName = String.format(mapNameFmt, new Object[] { layerName, zoom }); + String mapName = String.format(mapNameFmt, layerName, zoom); MapPolygon map = new MapPolygon(layer, mapName, mapSource, zoom, polygon, customTileParameters); layer.addMap(map); } diff --git a/src/main/java/mobac/gui/actions/AddRectangleMapAutocut.java b/mobac/src/main/java/mobac/gui/actions/AddRectangleMapAutocut.java similarity index 86% rename from src/main/java/mobac/gui/actions/AddRectangleMapAutocut.java rename to mobac/src/main/java/mobac/gui/actions/AddRectangleMapAutocut.java index 99ee627..e2138fa 100644 --- a/src/main/java/mobac/gui/actions/AddRectangleMapAutocut.java +++ b/mobac/src/main/java/mobac/gui/actions/AddRectangleMapAutocut.java @@ -1,27 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.Point; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JOptionPane; - import mobac.exceptions.InvalidNameException; import mobac.gui.MainGUI; import mobac.gui.atlastree.JAtlasTree; @@ -35,6 +29,11 @@ import mobac.program.model.Settings; import mobac.program.model.TileImageParameters; import mobac.utilities.I18nUtils; +import javax.swing.JOptionPane; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + public class AddRectangleMapAutocut implements ActionListener { public void actionPerformed(ActionEvent event) { @@ -53,7 +52,8 @@ public class AddRectangleMapAutocut implements ActionListener { Settings settings = Settings.getInstance(); // String errorText = mg.validateInput(); // if (errorText.length() > 0) { - // JOptionPane.showMessageDialog(mg, errorText, "Errors", JOptionPane.ERROR_MESSAGE); + // JOptionPane.showMessageDialog(mg, errorText, "Errors", + // JOptionPane.ERROR_MESSAGE); // return; // } @@ -72,7 +72,7 @@ public class AddRectangleMapAutocut implements ActionListener { layer = new Layer(atlasInterface, layerName); success = true; } catch (InvalidNameException e) { - layerName = name + "_" + Integer.toString(c++); + layerName = name + "_" + c++; } } while (!success); for (int zoom : zoomLevels) { @@ -80,8 +80,9 @@ public class AddRectangleMapAutocut implements ActionListener { Point br = ms.getBottomRightPixelCoordinate(zoom); TileImageParameters customTileParameters = mg.getSelectedTileImageParameters(); try { - String mapName = String.format(mapNameFmt, new Object[] { layerName, zoom }); - layer.addMapsAutocut(mapName, mapSource, tl, br, zoom, customTileParameters, settings.maxMapSize, settings.mapOverlapTiles); + String mapName = String.format(mapNameFmt, layerName, zoom); + layer.addMapsAutocut(mapName, mapSource, tl, br, zoom, customTileParameters, settings.maxMapSize, + settings.mapOverlapTiles); } catch (InvalidNameException e) { Logging.LOG.error("", e); } diff --git a/src/main/java/mobac/gui/actions/AtlasConvert.java b/mobac/src/main/java/mobac/gui/actions/AtlasConvert.java similarity index 80% rename from src/main/java/mobac/gui/actions/AtlasConvert.java rename to mobac/src/main/java/mobac/gui/actions/AtlasConvert.java index 94d42e9..6599b91 100644 --- a/src/main/java/mobac/gui/actions/AtlasConvert.java +++ b/mobac/src/main/java/mobac/gui/actions/AtlasConvert.java @@ -1,25 +1,24 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import mobac.gui.MainGUI; +import mobac.program.model.AtlasOutputFormat; +import mobac.utilities.I18nUtils; import javax.swing.JLabel; import javax.swing.JList; @@ -27,10 +26,10 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; - -import mobac.gui.MainGUI; -import mobac.program.model.AtlasOutputFormat; -import mobac.utilities.I18nUtils; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; public class AtlasConvert implements ActionListener { @@ -44,9 +43,10 @@ public class AtlasConvert implements ActionListener { JPanel formatPanel = new JPanel(new BorderLayout()); formatPanel.setPreferredSize(new Dimension(250, 300)); - - formatPanel.add(new JLabel(I18nUtils.localizedStringForKey("dlg_new_atlas_select_format_title")), BorderLayout.NORTH); - JList atlasFormatList = new JList(AtlasOutputFormat.getFormatsAsVector()); + + formatPanel.add(new JLabel(I18nUtils.localizedStringForKey("dlg_new_atlas_select_format_title")), + BorderLayout.NORTH); + JList atlasFormatList = new JList<>(AtlasOutputFormat.getFormatsAsVector()); atlasFormatList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JScrollPane scroller = new JScrollPane(atlasFormatList); scroller.setPreferredSize(new Dimension(100, 200)); @@ -58,16 +58,18 @@ public class AtlasConvert implements ActionListener { currentAOF = mg.getAtlas().getOutputFormat(); } catch (Exception e) { } - if (currentAOF != null) + if (currentAOF != null) { atlasFormatList.setSelectedValue(currentAOF, true); - else + } else { atlasFormatList.setSelectedIndex(1); - int result = JOptionPane.showConfirmDialog(MainGUI.getMainGUI(), panel, I18nUtils.localizedStringForKey("msg_convert_atlas_format"), - JOptionPane.OK_CANCEL_OPTION); - if (result != JOptionPane.OK_OPTION) + } + int result = JOptionPane.showConfirmDialog(MainGUI.getMainGUI(), panel, + I18nUtils.localizedStringForKey("msg_convert_atlas_format"), JOptionPane.OK_CANCEL_OPTION); + if (result != JOptionPane.OK_OPTION) { return; + } - AtlasOutputFormat format = (AtlasOutputFormat) atlasFormatList.getSelectedValue(); + AtlasOutputFormat format = atlasFormatList.getSelectedValue(); mg.jAtlasTree.convertAtlas(format); mg.getParametersPanel().atlasFormatChanged(format); } diff --git a/src/main/java/mobac/gui/actions/AtlasCreate.java b/mobac/src/main/java/mobac/gui/actions/AtlasCreate.java similarity index 89% rename from src/main/java/mobac/gui/actions/AtlasCreate.java rename to mobac/src/main/java/mobac/gui/actions/AtlasCreate.java index 8c38931..8cf71e1 100644 --- a/src/main/java/mobac/gui/actions/AtlasCreate.java +++ b/mobac/src/main/java/mobac/gui/actions/AtlasCreate.java @@ -1,43 +1,43 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JOptionPane; - import mobac.exceptions.AtlasTestException; import mobac.gui.atlastree.JAtlasTree; import mobac.program.AtlasThread; import mobac.program.interfaces.AtlasInterface; import mobac.utilities.I18nUtils; +import javax.swing.JOptionPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + public class AtlasCreate implements ActionListener { - private JAtlasTree jAtlasTree; + private final JAtlasTree jAtlasTree; public AtlasCreate(JAtlasTree jAtlasTree) { this.jAtlasTree = jAtlasTree; } public void actionPerformed(ActionEvent event) { - if (!jAtlasTree.testAtlasContentValid()) + if (!jAtlasTree.testAtlasContentValid()) { return; + } try { // We have to work on a deep clone otherwise the user would be // able to modify settings of maps, layers and the atlas itself diff --git a/src/main/java/mobac/gui/actions/AtlasNew.java b/mobac/src/main/java/mobac/gui/actions/AtlasNew.java similarity index 81% rename from src/main/java/mobac/gui/actions/AtlasNew.java rename to mobac/src/main/java/mobac/gui/actions/AtlasNew.java index afc98c6..c739e51 100644 --- a/src/main/java/mobac/gui/actions/AtlasNew.java +++ b/mobac/src/main/java/mobac/gui/actions/AtlasNew.java @@ -1,25 +1,24 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import mobac.gui.MainGUI; +import mobac.program.model.AtlasOutputFormat; +import mobac.utilities.I18nUtils; import javax.swing.JLabel; import javax.swing.JList; @@ -28,10 +27,10 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.ListSelectionModel; - -import mobac.gui.MainGUI; -import mobac.program.model.AtlasOutputFormat; -import mobac.utilities.I18nUtils; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; public class AtlasNew implements ActionListener { @@ -44,8 +43,9 @@ public class AtlasNew implements ActionListener { JPanel formatPanel = new JPanel(new BorderLayout()); - formatPanel.add(new JLabel(I18nUtils.localizedStringForKey("dlg_new_atlas_select_format_title")), BorderLayout.NORTH); - JList atlasFormatList = new JList(AtlasOutputFormat.getFormatsAsVector()); + formatPanel.add(new JLabel(I18nUtils.localizedStringForKey("dlg_new_atlas_select_format_title")), + BorderLayout.NORTH); + JList atlasFormatList = new JList<>(AtlasOutputFormat.getFormatsAsVector()); atlasFormatList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); JScrollPane scroller = new JScrollPane(atlasFormatList); scroller.setPreferredSize(new Dimension(140, 200)); @@ -58,22 +58,24 @@ public class AtlasNew implements ActionListener { panel.add(namePanel, BorderLayout.NORTH); panel.add(formatPanel, BorderLayout.CENTER); - panel.setPreferredSize(new Dimension(300, 300)); + panel.setPreferredSize(new Dimension(300, 300)); AtlasOutputFormat currentAOF = null; try { currentAOF = mg.getAtlas().getOutputFormat(); } catch (Exception e) { } - if (currentAOF != null) + if (currentAOF != null) { atlasFormatList.setSelectedValue(currentAOF, true); - else + } else { atlasFormatList.setSelectedIndex(1); - int result = JOptionPane.showConfirmDialog(MainGUI.getMainGUI(), panel, I18nUtils.localizedStringForKey("dlg_new_atlas_title"), - JOptionPane.OK_CANCEL_OPTION); - if (result != JOptionPane.OK_OPTION) + } + int result = JOptionPane.showConfirmDialog(MainGUI.getMainGUI(), panel, + I18nUtils.localizedStringForKey("dlg_new_atlas_title"), JOptionPane.OK_CANCEL_OPTION); + if (result != JOptionPane.OK_OPTION) { return; + } - AtlasOutputFormat format = (AtlasOutputFormat) atlasFormatList.getSelectedValue(); + AtlasOutputFormat format = atlasFormatList.getSelectedValue(); mg.jAtlasTree.newAtlas(atlasName.getText(), format); mg.getParametersPanel().atlasFormatChanged(format); } diff --git a/src/main/java/mobac/gui/actions/BookmarkAdd.java b/mobac/src/main/java/mobac/gui/actions/BookmarkAdd.java similarity index 87% rename from src/main/java/mobac/gui/actions/BookmarkAdd.java rename to mobac/src/main/java/mobac/gui/actions/BookmarkAdd.java index 712c02d..4ced9df 100644 --- a/src/main/java/mobac/gui/actions/BookmarkAdd.java +++ b/mobac/src/main/java/mobac/gui/actions/BookmarkAdd.java @@ -1,32 +1,31 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JOptionPane; - import mobac.gui.MainGUI; import mobac.gui.mapview.PreviewMap; import mobac.program.model.Bookmark; import mobac.program.model.Settings; import mobac.utilities.I18nUtils; +import javax.swing.JOptionPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + public class BookmarkAdd implements ActionListener { private final PreviewMap previewMap; @@ -37,9 +36,11 @@ public class BookmarkAdd implements ActionListener { public void actionPerformed(ActionEvent arg0) { Bookmark bm = previewMap.getPositionBookmark(); - String name = JOptionPane.showInputDialog(I18nUtils.localizedStringForKey("dlg_add_bookmark_msg"), bm.toString()); - if (name == null) + String name = JOptionPane.showInputDialog(I18nUtils.localizedStringForKey("dlg_add_bookmark_msg"), + bm.toString()); + if (name == null) { return; + } bm.setName(name); Settings.getInstance().placeBookmarks.add(bm); MainGUI.getMainGUI().updateBookmarksMenu(); diff --git a/src/main/java/mobac/gui/actions/BookmarkManage.java b/mobac/src/main/java/mobac/gui/actions/BookmarkManage.java similarity index 90% rename from src/main/java/mobac/gui/actions/BookmarkManage.java rename to mobac/src/main/java/mobac/gui/actions/BookmarkManage.java index 76f0739..18e7e61 100644 --- a/src/main/java/mobac/gui/actions/BookmarkManage.java +++ b/mobac/src/main/java/mobac/gui/actions/BookmarkManage.java @@ -1,27 +1,27 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - import mobac.gui.MainGUI; import mobac.gui.dialogs.ManageBookmarks; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + public class BookmarkManage implements ActionListener { public void actionPerformed(ActionEvent event) { diff --git a/src/main/java/mobac/gui/actions/DebugSetLogLevel.java b/mobac/src/main/java/mobac/gui/actions/DebugSetLogLevel.java similarity index 78% rename from src/main/java/mobac/gui/actions/DebugSetLogLevel.java rename to mobac/src/main/java/mobac/gui/actions/DebugSetLogLevel.java index 7507ebc..2fe1593 100644 --- a/src/main/java/mobac/gui/actions/DebugSetLogLevel.java +++ b/mobac/src/main/java/mobac/gui/actions/DebugSetLogLevel.java @@ -1,39 +1,38 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import mobac.gui.MainGUI; +import org.slf4j.LoggerFactory; + +import javax.swing.JMenu; +import javax.swing.JMenuItem; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import javax.swing.JMenu; -import javax.swing.JMenuItem; - -import mobac.gui.MainGUI; - -import org.apache.log4j.Level; -import org.apache.log4j.Logger; - public class DebugSetLogLevel implements ActionListener { public void actionPerformed(ActionEvent event) { - Logger log = Logger.getRootLogger(); + Logger root = (Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); JMenuItem menuItem = (JMenuItem) event.getSource(); - log.setLevel(Level.toLevel(menuItem.getName())); + root.setLevel(Level.toLevel(menuItem.getName())); JMenu menu = MainGUI.getMainGUI().logLevelMenu; Component[] c = menu.getMenuComponents(); for (int i = 0; i < c.length; i++) { diff --git a/src/main/java/mobac/gui/actions/DebugShowLogFile.java b/mobac/src/main/java/mobac/gui/actions/DebugShowLogFile.java similarity index 81% rename from src/main/java/mobac/gui/actions/DebugShowLogFile.java rename to mobac/src/main/java/mobac/gui/actions/DebugShowLogFile.java index 9ed2ca7..c3952f4 100644 --- a/src/main/java/mobac/gui/actions/DebugShowLogFile.java +++ b/mobac/src/main/java/mobac/gui/actions/DebugShowLogFile.java @@ -1,53 +1,51 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; +import mobac.gui.MainGUI; +import mobac.program.Logging; +import mobac.utilities.GUIExceptionHandler; +import mobac.utilities.I18nUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.JOptionPane; import java.awt.Desktop; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.io.IOException; -import javax.swing.JOptionPane; - -import mobac.gui.MainGUI; -import mobac.program.Logging; -import mobac.utilities.GUIExceptionHandler; -import mobac.utilities.I18nUtils; - -import org.apache.log4j.Logger; - public class DebugShowLogFile implements ActionListener { public void actionPerformed(ActionEvent event) { - Logger log = Logger.getLogger(DebugShowLogFile.class); + Logger log = LoggerFactory.getLogger(DebugShowLogFile.class); String logFile = Logging.getLogFile(); if (logFile == null) { log.error("No file logger configured"); - JOptionPane.showMessageDialog(MainGUI.getMainGUI(), - I18nUtils.localizedStringForKey("msg_no_log_file_config"), - I18nUtils.localizedStringForKey("Error"), + JOptionPane.showMessageDialog(MainGUI.getMainGUI(), + I18nUtils.localizedStringForKey("msg_no_log_file_config"), I18nUtils.localizedStringForKey("Error"), JOptionPane.ERROR_MESSAGE); return; } File f = new File(logFile); if (!f.isFile()) { log.error("Log file does not exists: " + f.getAbsolutePath()); - JOptionPane.showMessageDialog(MainGUI.getMainGUI(), + JOptionPane.showMessageDialog(MainGUI.getMainGUI(), String.format(I18nUtils.localizedStringForKey("msg_no_log_file"), f.getAbsolutePath()), I18nUtils.localizedStringForKey("Error"), JOptionPane.ERROR_MESSAGE); return; diff --git a/src/main/java/mobac/gui/actions/DebugShowMapSourceNames.java b/mobac/src/main/java/mobac/gui/actions/DebugShowMapSourceNames.java similarity index 71% rename from src/main/java/mobac/gui/actions/DebugShowMapSourceNames.java rename to mobac/src/main/java/mobac/gui/actions/DebugShowMapSourceNames.java index 92d7f1f..db76268 100644 --- a/src/main/java/mobac/gui/actions/DebugShowMapSourceNames.java +++ b/mobac/src/main/java/mobac/gui/actions/DebugShowMapSourceNames.java @@ -1,21 +1,31 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; +import mobac.gui.MainGUI; +import mobac.mapsources.MapSourcesManager; +import mobac.program.interfaces.MapSource; +import mobac.program.model.MapSourceLoaderInfo; +import mobac.utilities.I18nUtils; + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; import java.awt.Dimension; import java.awt.Toolkit; import java.awt.event.ActionEvent; @@ -26,22 +36,11 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; -import javax.swing.JFrame; -import javax.swing.JScrollPane; -import javax.swing.JTable; -import javax.swing.table.AbstractTableModel; - -import mobac.gui.MainGUI; -import mobac.mapsources.MapSourcesManager; -import mobac.program.interfaces.MapSource; -import mobac.program.model.MapSourceLoaderInfo; -import mobac.utilities.I18nUtils; - public class DebugShowMapSourceNames implements ActionListener { public void actionPerformed(ActionEvent e) { - ArrayList mapSources = new ArrayList(MapSourcesManager.getInstance() - .getAllAvailableMapSources()); + ArrayList mapSources = new ArrayList( + MapSourcesManager.getInstance().getAllAvailableMapSources()); Collections.sort(mapSources, new Comparator() { @@ -86,16 +85,16 @@ public class DebugShowMapSourceNames implements ActionListener { @Override public String getColumnName(int column) { switch (column) { - case 0: - return I18nUtils.localizedStringForKey("dlg_show_source_column_name"); - case 1: - return I18nUtils.localizedStringForKey("dlg_show_source_column_display_text"); - case 2: - return I18nUtils.localizedStringForKey("dlg_show_source_column_rev"); - case 3: - return I18nUtils.localizedStringForKey("dlg_show_source_column_type"); - default: - return null; + case 0 : + return I18nUtils.localizedStringForKey("dlg_show_source_column_name"); + case 1 : + return I18nUtils.localizedStringForKey("dlg_show_source_column_display_text"); + case 2 : + return I18nUtils.localizedStringForKey("dlg_show_source_column_rev"); + case 3 : + return I18nUtils.localizedStringForKey("dlg_show_source_column_type"); + default : + return null; } } @@ -103,26 +102,29 @@ public class DebugShowMapSourceNames implements ActionListener { MapSource ms = mapSources.get(rowIndex); MapSourceLoaderInfo li; switch (columnIndex) { - case 0: - return ms.getName(); - case 1: - return ms.toString(); - case 2: - li = ms.getLoaderInfo(); - if (li == null) + case 0 : + return ms.getName(); + case 1 : + return ms.toString(); + case 2 : + li = ms.getLoaderInfo(); + if (li == null) { + return null; + } + return li.getRevision(); + case 3 : + li = ms.getLoaderInfo(); + if (li == null) { + return null; + } + String s = ""; + File f = li.getSourceFile(); + if (f != null) { + s += f.getName() + " / "; + } + return s + li.getLoaderType(); + default : return null; - return li.getRevision(); - case 3: - li = ms.getLoaderInfo(); - if (li == null) - return null; - String s = ""; - File f = li.getSourceFile(); - if (f != null) - s += f.getName() + " / "; - return s + li.getLoaderType(); - default: - return null; } } } diff --git a/src/main/java/mobac/gui/actions/DebugShowMapTileGrid.java b/mobac/src/main/java/mobac/gui/actions/DebugShowMapTileGrid.java similarity index 91% rename from src/main/java/mobac/gui/actions/DebugShowMapTileGrid.java rename to mobac/src/main/java/mobac/gui/actions/DebugShowMapTileGrid.java index 3524bc6..b11900c 100644 --- a/src/main/java/mobac/gui/actions/DebugShowMapTileGrid.java +++ b/mobac/src/main/java/mobac/gui/actions/DebugShowMapTileGrid.java @@ -1,29 +1,28 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JCheckBoxMenuItem; - import mobac.gui.MainGUI; import mobac.gui.mapview.PreviewMap; +import javax.swing.JCheckBoxMenuItem; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + public class DebugShowMapTileGrid implements ActionListener { public void actionPerformed(ActionEvent e) { diff --git a/src/main/java/mobac/gui/actions/DebugShowReport.java b/mobac/src/main/java/mobac/gui/actions/DebugShowReport.java similarity index 75% rename from src/main/java/mobac/gui/actions/DebugShowReport.java rename to mobac/src/main/java/mobac/gui/actions/DebugShowReport.java index f2c26b1..030e2dd 100644 --- a/src/main/java/mobac/gui/actions/DebugShowReport.java +++ b/mobac/src/main/java/mobac/gui/actions/DebugShowReport.java @@ -1,31 +1,35 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; +import mobac.utilities.GUIExceptionHandler; +import mobac.utilities.GUIExceptionHandler.NotABug; + import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import mobac.utilities.GUIExceptionHandler; - public class DebugShowReport implements ActionListener { public void actionPerformed(ActionEvent e) { - GUIExceptionHandler.processException(null, null); + GUIExceptionHandler.processException(Thread.currentThread(), new SystemReport()); // throw new RuntimeException("Test"); } + private static final class SystemReport extends RuntimeException implements NotABug { + + } } diff --git a/src/main/java/mobac/gui/actions/GpxAddPoint.java b/mobac/src/main/java/mobac/gui/actions/GpxAddPoint.java similarity index 77% rename from src/main/java/mobac/gui/actions/GpxAddPoint.java rename to mobac/src/main/java/mobac/gui/actions/GpxAddPoint.java index 7c80d20..7773b37 100644 --- a/src/main/java/mobac/gui/actions/GpxAddPoint.java +++ b/mobac/src/main/java/mobac/gui/actions/GpxAddPoint.java @@ -1,26 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JOptionPane; - import mobac.gui.MainGUI; import mobac.gui.gpxtree.GpxEntry; import mobac.gui.mapview.PreviewMap; @@ -28,12 +23,14 @@ import mobac.gui.mapview.controller.GpxMapController; import mobac.gui.panels.JGpxPanel; import mobac.utilities.I18nUtils; - +import javax.swing.JOptionPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; public class GpxAddPoint implements ActionListener { JGpxPanel panel; - + private GpxMapController mapController = null; public GpxAddPoint(JGpxPanel panel) { @@ -46,25 +43,25 @@ public class GpxAddPoint implements ActionListener { if (entry == null) { int answer = JOptionPane.showConfirmDialog(null, I18nUtils.localizedStringForKey("rp_gpx_msg_ask_create_new"), - I18nUtils.localizedStringForKey("rp_gpx_msg_ask_create_new_title"), - JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - if (answer != JOptionPane.YES_OPTION) + I18nUtils.localizedStringForKey("rp_gpx_msg_ask_create_new_title"), JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE); + if (answer != JOptionPane.YES_OPTION) { return; + } entry = new GpxNew(panel).newGpx(); } - + if (!entry.isWaypointParent()) { - JOptionPane.showMessageDialog(null, - I18nUtils.localizedStringForKey("rp_gpx_msg_add_point_failed"), - I18nUtils.localizedStringForKey("Error"), - JOptionPane.INFORMATION_MESSAGE); + JOptionPane.showMessageDialog(null, I18nUtils.localizedStringForKey("rp_gpx_msg_add_point_failed"), + I18nUtils.localizedStringForKey("Error"), JOptionPane.INFORMATION_MESSAGE); return; } - + PreviewMap map = MainGUI.getMainGUI().previewMap; map.getMapSelectionController().disable(); - if (mapController == null) + if (mapController == null) { mapController = new GpxMapController(map, panel, false); + } mapController.enable(); } } diff --git a/src/main/java/mobac/gui/actions/GpxClear.java b/mobac/src/main/java/mobac/gui/actions/GpxClear.java similarity index 88% rename from src/main/java/mobac/gui/actions/GpxClear.java rename to mobac/src/main/java/mobac/gui/actions/GpxClear.java index 5f5330d..a466ae9 100644 --- a/src/main/java/mobac/gui/actions/GpxClear.java +++ b/mobac/src/main/java/mobac/gui/actions/GpxClear.java @@ -1,38 +1,35 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Iterator; - import mobac.gui.MainGUI; import mobac.gui.mapview.interfaces.MapLayer; import mobac.gui.mapview.layer.GpxLayer; import mobac.gui.panels.JGpxPanel; - +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Iterator; /** * Deletes all loaded {@link GpxLayer}s from the main map viewer. - * */ public class GpxClear implements ActionListener { - + JGpxPanel panel; public GpxClear(JGpxPanel panel) { @@ -43,8 +40,9 @@ public class GpxClear implements ActionListener { public void actionPerformed(ActionEvent e) { Iterator mapLayers = MainGUI.getMainGUI().previewMap.mapLayers.iterator(); while (mapLayers.hasNext()) { - if (mapLayers.next() instanceof GpxLayer) + if (mapLayers.next() instanceof GpxLayer) { mapLayers.remove(); + } } panel.resetModel(); MainGUI.getMainGUI().previewMap.repaint(); diff --git a/src/main/java/mobac/gui/actions/GpxEditor.java b/mobac/src/main/java/mobac/gui/actions/GpxEditor.java similarity index 93% rename from src/main/java/mobac/gui/actions/GpxEditor.java rename to mobac/src/main/java/mobac/gui/actions/GpxEditor.java index 51ee769..8e9a6e5 100644 --- a/src/main/java/mobac/gui/actions/GpxEditor.java +++ b/mobac/src/main/java/mobac/gui/actions/GpxEditor.java @@ -1,25 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.util.List; - -import javax.swing.tree.DefaultMutableTreeNode; - import mobac.data.gpx.gpx11.Gpx; import mobac.data.gpx.gpx11.RteType; import mobac.data.gpx.gpx11.TrkType; @@ -30,11 +26,13 @@ import mobac.gui.gpxtree.RteEntry; import mobac.gui.gpxtree.TrkEntry; import mobac.gui.gpxtree.TrksegEntry; +import javax.swing.tree.DefaultMutableTreeNode; +import java.util.List; + /** * Encapsulates all functionality regarding edits of loaded gpx files. - * + * * @author lhoeppner - * */ public class GpxEditor { private static GpxEditor editor = null; @@ -48,7 +46,7 @@ public class GpxEditor { /** * Adds a wpt to the selected route. - * + * * @param entry * @param wpt */ @@ -64,7 +62,7 @@ public class GpxEditor { /** * Adds a wpt to the selected track segment. - * + * * @param entry * @param wpt */ @@ -86,7 +84,7 @@ public class GpxEditor { /** * Removes a waypoint from the Gpx assigned to the layer. - * + * * @param wpt * - the node to be removed * @return - true if wpt found and deleted, false otherwise diff --git a/src/main/java/mobac/gui/actions/GpxElementListener.java b/mobac/src/main/java/mobac/gui/actions/GpxElementListener.java similarity index 62% rename from src/main/java/mobac/gui/actions/GpxElementListener.java rename to mobac/src/main/java/mobac/gui/actions/GpxElementListener.java index c09250d..d5d83f6 100644 --- a/src/main/java/mobac/gui/actions/GpxElementListener.java +++ b/mobac/src/main/java/mobac/gui/actions/GpxElementListener.java @@ -1,27 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; - -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; - import mobac.data.gpx.gpx11.WptType; import mobac.gui.MainGUI; import mobac.gui.gpxtree.GpxEntry; @@ -34,12 +28,16 @@ import mobac.gui.mapview.PreviewMap; import mobac.gui.mapview.controller.GpxMapController; import mobac.utilities.I18nUtils; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + /** * Listener for the gpx editor tree elements. - * + * * @author lhoeppner * @author r_x - * */ public class GpxElementListener implements MouseListener { @@ -47,9 +45,8 @@ public class GpxElementListener implements MouseListener { public static final String MENU_NAME_DELETE = I18nUtils.localizedStringForKey("rp_gpx_menu_delete"); private final GpxEntry gpxEntry; - + private final GpxEditor editor = GpxEditor.getInstance(); private GpxMapController mapController = null; - private GpxEditor editor = GpxEditor.getInstance(); public GpxElementListener(GpxEntry gpxEntry) { this.gpxEntry = gpxEntry; @@ -74,8 +71,9 @@ public class GpxElementListener implements MouseListener { private void handleClick(MouseEvent e) { JMenuItem item = (JMenuItem) e.getSource(); - if (item == null) + if (item == null) { return; + } if (MENU_NAME_RENAME.equals(item.getName())) { renameEntry(); } else if (MENU_NAME_DELETE.equals(item.getName())) { @@ -84,20 +82,19 @@ public class GpxElementListener implements MouseListener { } /** - * Removes an entry (wpt, trk, trkseg, rte) from a gpx file (and the displayed layer) Currently only works for - * waypoints. - * + * Removes an entry (wpt, trk, trkseg, rte) from a gpx file (and the displayed + * layer) Currently only works for waypoints. */ private void removeEntry() { - int answer = JOptionPane.showConfirmDialog(null, - I18nUtils.localizedStringForKey("rp_gpx_msg_confim_delete"), - I18nUtils.localizedStringForKey("rp_gpx_msg_confim_delete_title"), - JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); + int answer = JOptionPane.showConfirmDialog(null, I18nUtils.localizedStringForKey("rp_gpx_msg_confim_delete"), + I18nUtils.localizedStringForKey("rp_gpx_msg_confim_delete_title"), JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE); if (answer == JOptionPane.YES_OPTION) { PreviewMap map = MainGUI.getMainGUI().previewMap; map.getMapSelectionController().disable(); - if (mapController == null) + if (mapController == null) { mapController = new GpxMapController(map, gpxEntry.getLayer().getPanel(), false); + } mapController.enable(); if (gpxEntry.getClass().equals(RteEntry.class)) { @@ -116,54 +113,52 @@ public class GpxElementListener implements MouseListener { // GpxRootEntry root = (GpxRootEntry) gpxEntry; } - } else { - return; } } /** * Renames (if possible) the entry according to user input. - * */ private void renameEntry() { if (gpxEntry.getClass().equals(TrksegEntry.class)) { - JOptionPane.showMessageDialog(null, - I18nUtils.localizedStringForKey("rp_gpx_msg_can_not_rename_track"), - I18nUtils.localizedStringForKey("Error"), - JOptionPane.INFORMATION_MESSAGE); + JOptionPane.showMessageDialog(null, I18nUtils.localizedStringForKey("rp_gpx_msg_can_not_rename_track"), + I18nUtils.localizedStringForKey("Error"), JOptionPane.INFORMATION_MESSAGE); return; - } else { - if (gpxEntry.getClass().equals(RteEntry.class)) { - RteEntry rte = (RteEntry) gpxEntry; - String name = JOptionPane.showInputDialog(null, I18nUtils.localizedStringForKey("rp_gpx_rename_element_title"), - rte.getRte().getName()); - if (name == null) { - return; - } - rte.getRte().setName(name); - } else if (gpxEntry.getClass().equals(TrkEntry.class)) { - TrkEntry trk = (TrkEntry) gpxEntry; - String name = JOptionPane.showInputDialog(null, I18nUtils.localizedStringForKey("rp_gpx_rename_element_title"), trk.getTrk().getName()); - if (name == null) { - return; - } - trk.getTrk().setName(name); - } else if (gpxEntry.getClass().equals(WptEntry.class)) { - WptEntry wpt = (WptEntry) gpxEntry; - String name = JOptionPane.showInputDialog(null, I18nUtils.localizedStringForKey("rp_gpx_rename_element_title"), wpt.getWpt().getName()); - if (name == null) { - return; - } - wpt.getWpt().setName(name); - } else if (gpxEntry.getClass().equals(GpxRootEntry.class)) { - GpxRootEntry root = (GpxRootEntry) gpxEntry; - String initialValue = root.getMetaDataName(); - String name = JOptionPane.showInputDialog(null, I18nUtils.localizedStringForKey("rp_gpx_rename_element_title"), initialValue); - if (name == null) { - return; - } - root.setMetaDataName(name); - } } + if (gpxEntry.getClass().equals(RteEntry.class)) { + RteEntry rte = (RteEntry) gpxEntry; + String name = JOptionPane.showInputDialog(null, + I18nUtils.localizedStringForKey("rp_gpx_rename_element_title"), rte.getRte().getName()); + if (name == null) { + return; + } + rte.getRte().setName(name); + } else if (gpxEntry.getClass().equals(TrkEntry.class)) { + TrkEntry trk = (TrkEntry) gpxEntry; + String name = JOptionPane.showInputDialog(null, + I18nUtils.localizedStringForKey("rp_gpx_rename_element_title"), trk.getTrk().getName()); + if (name == null) { + return; + } + trk.getTrk().setName(name); + } else if (gpxEntry.getClass().equals(WptEntry.class)) { + WptEntry wpt = (WptEntry) gpxEntry; + String name = JOptionPane.showInputDialog(null, + I18nUtils.localizedStringForKey("rp_gpx_rename_element_title"), wpt.getWpt().getName()); + if (name == null) { + return; + } + wpt.getWpt().setName(name); + } else if (gpxEntry.getClass().equals(GpxRootEntry.class)) { + GpxRootEntry root = (GpxRootEntry) gpxEntry; + String initialValue = root.getMetaDataName(); + String name = JOptionPane.showInputDialog(null, + I18nUtils.localizedStringForKey("rp_gpx_rename_element_title"), initialValue); + if (name == null) { + return; + } + root.setMetaDataName(name); + } + } } diff --git a/src/main/java/mobac/gui/actions/GpxLoad.java b/mobac/src/main/java/mobac/gui/actions/GpxLoad.java similarity index 75% rename from src/main/java/mobac/gui/actions/GpxLoad.java rename to mobac/src/main/java/mobac/gui/actions/GpxLoad.java index 5ca118a..8b199c3 100644 --- a/src/main/java/mobac/gui/actions/GpxLoad.java +++ b/mobac/src/main/java/mobac/gui/actions/GpxLoad.java @@ -1,35 +1,22 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.Component; -import java.awt.Cursor; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; - -import javax.swing.JDialog; -import javax.swing.JFileChooser; -import javax.swing.JOptionPane; -import javax.swing.JProgressBar; -import javax.swing.SwingUtilities; -import javax.swing.WindowConstants; -import javax.xml.bind.JAXBException; - +import jakarta.xml.bind.JAXBException; import mobac.data.gpx.GPXUtils; import mobac.data.gpx.gpx11.Gpx; import mobac.gui.MainGUI; @@ -38,13 +25,24 @@ import mobac.gui.panels.JGpxPanel; import mobac.program.model.Settings; import mobac.utilities.I18nUtils; import mobac.utilities.file.GpxFileFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Logger; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JProgressBar; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; public class GpxLoad implements ActionListener { - private Logger log = Logger.getLogger(GpxLoad.class); - + private final Logger log = LoggerFactory.getLogger(GpxLoad.class); JGpxPanel panel; public GpxLoad(JGpxPanel panel) { @@ -53,20 +51,21 @@ public class GpxLoad implements ActionListener { } public void actionPerformed(ActionEvent event) { - if (!GPXUtils.checkJAXBVersion()) - return; JFileChooser fc = new JFileChooser(); + String gpxFileChooserDir = Settings.getInstance().gpxFileChooserDir; try { - File dir = new File(Settings.getInstance().gpxFileChooserDir); + File dir = new File(gpxFileChooserDir); fc.setCurrentDirectory(dir); // restore the saved directory } catch (Exception e) { + log.error("Failed to change the current directory to " + gpxFileChooserDir, e); } fc.setMultiSelectionEnabled(true); fc.addChoosableFileFilter(new GpxFileFilter(false)); final MainGUI mainGUI = MainGUI.getMainGUI(); int returnVal = fc.showOpenDialog(mainGUI); - if (returnVal != JFileChooser.APPROVE_OPTION) + if (returnVal != JFileChooser.APPROVE_OPTION) { return; + } Settings.getInstance().gpxFileChooserDir = fc.getCurrentDirectory().getAbsolutePath(); File[] f = fc.getSelectedFiles(); @@ -75,16 +74,18 @@ public class GpxLoad implements ActionListener { boolean duplicates = false; for (File selectedFile : f) { duplicates = panel.isFileOpen(selectedFile.getAbsolutePath()); - if (duplicates) + if (duplicates) { break; + } } if (duplicates) { - int answer = JOptionPane - .showConfirmDialog(mainGUI, I18nUtils.localizedStringForKey("rp_gpx_msg_confirm_reopen_file"), - I18nUtils.localizedStringForKey("Warning"), JOptionPane.YES_NO_OPTION, - JOptionPane.QUESTION_MESSAGE); - if (answer != JOptionPane.YES_OPTION) + int answer = JOptionPane.showConfirmDialog(mainGUI, + I18nUtils.localizedStringForKey("rp_gpx_msg_confirm_reopen_file"), + I18nUtils.localizedStringForKey("Warning"), JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE); + if (answer != JOptionPane.YES_OPTION) { return; + } } // process @@ -106,10 +107,11 @@ public class GpxLoad implements ActionListener { gpxLayer.setFile(f); panel.addGpxLayer(gpxLayer); } catch (JAXBException e) { - JOptionPane.showMessageDialog(parent, "Unable to load the GPX file
" + f.getAbsolutePath() - + "

Please make sure the file is a valid GPX v1.1 file.
" - + "
Internal error message:
" + e.getMessage() + "", "GPX loading failed", - JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(parent, + "Unable to load the GPX file
" + f.getAbsolutePath() + + "

Please make sure the file is a valid GPX v1.1 file.
" + + "
Internal error message:
" + e.getMessage() + "", + "GPX loading failed", JOptionPane.ERROR_MESSAGE); throw new RuntimeException(e); } } @@ -142,8 +144,8 @@ public class GpxLoad implements ActionListener { SwingUtilities.invokeLater(new Runnable() { public void run() { progressBar.setValue(counter); - progressDialog.setTitle("Processing " + counter + " of " + files.length + " <" - + file.getName() + ">"); + progressDialog.setTitle( + "Processing " + counter + " of " + files.length + " <" + file.getName() + ">"); } }); doLoad(file, progressDialog); @@ -165,7 +167,8 @@ public class GpxLoad implements ActionListener { } }); } - }; + } + }; job.start(); diff --git a/src/main/java/mobac/gui/actions/GpxNew.java b/mobac/src/main/java/mobac/gui/actions/GpxNew.java similarity index 87% rename from src/main/java/mobac/gui/actions/GpxNew.java rename to mobac/src/main/java/mobac/gui/actions/GpxNew.java index 23d961b..745641a 100644 --- a/src/main/java/mobac/gui/actions/GpxNew.java +++ b/mobac/src/main/java/mobac/gui/actions/GpxNew.java @@ -1,32 +1,30 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import mobac.data.gpx.GPXUtils; import mobac.data.gpx.gpx11.Gpx; import mobac.gui.MainGUI; import mobac.gui.gpxtree.GpxRootEntry; import mobac.gui.mapview.layer.GpxLayer; import mobac.gui.panels.JGpxPanel; -//import mobac.gui.panels.JGpxPanel.ListModelEntry; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +//import mobac.gui.panels.JGpxPanel.ListModelEntry; public class GpxNew implements ActionListener { @@ -38,8 +36,6 @@ public class GpxNew implements ActionListener { } public void actionPerformed(ActionEvent event) { - if (!GPXUtils.checkJAXBVersion()) - return; newGpx(); MainGUI.getMainGUI().previewMap.repaint(); } diff --git a/src/main/java/mobac/gui/actions/GpxSave.java b/mobac/src/main/java/mobac/gui/actions/GpxSave.java similarity index 79% rename from src/main/java/mobac/gui/actions/GpxSave.java rename to mobac/src/main/java/mobac/gui/actions/GpxSave.java index 8ae27f9..889e21e 100644 --- a/src/main/java/mobac/gui/actions/GpxSave.java +++ b/mobac/src/main/java/mobac/gui/actions/GpxSave.java @@ -1,29 +1,22 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; - -import javax.swing.JFileChooser; -import javax.swing.JOptionPane; -import javax.xml.bind.JAXBException; - +import jakarta.xml.bind.JAXBException; import mobac.data.gpx.GPXUtils; import mobac.data.gpx.gpx11.Gpx; import mobac.gui.MainGUI; @@ -33,18 +26,22 @@ import mobac.program.model.Settings; import mobac.utilities.I18nUtils; import mobac.utilities.file.GpxFileFilter; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; public class GpxSave implements ActionListener { - private JGpxPanel panel; - private boolean saveAs; + private final JGpxPanel panel; + private final boolean saveAs; public GpxSave(JGpxPanel panel) { this(panel, false); } /** - * * @param panel * @param saveAs * if true a file chooser dialog is displayed where the user can @@ -60,25 +57,23 @@ public class GpxSave implements ActionListener { GpxEntry entry = panel.getSelectedEntry(); if (entry == null) { - JOptionPane.showMessageDialog(null, - I18nUtils.localizedStringForKey("rp_gpx_msg_error_save_gpx_file"), - I18nUtils.localizedStringForKey("rp_gpx_msg_no_select_file"), - JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(null, I18nUtils.localizedStringForKey("rp_gpx_msg_error_save_gpx_file"), + I18nUtils.localizedStringForKey("rp_gpx_msg_no_select_file"), JOptionPane.ERROR_MESSAGE); return; } - if (!GPXUtils.checkJAXBVersion()) - return; - Gpx gpx = entry.getLayer().getGpx(); try { File f = entry.getLayer().getFile(); - if (saveAs || f == null) + if (saveAs || f == null) { f = selectFile(f); - if (f == null) + } + if (f == null) { return; - if (!f.getName().toLowerCase().endsWith(".gpx")) + } + if (!f.getName().toLowerCase().endsWith(".gpx")) { f = new File(f.getAbsolutePath() + ".gpx"); + } entry.getLayer().setFile(f); GPXUtils.saveGpxFile(gpx, f); } catch (JAXBException e) { @@ -91,16 +86,18 @@ public class GpxSave implements ActionListener { JFileChooser fc = new JFileChooser(); try { File dir = new File(Settings.getInstance().gpxFileChooserDir); - if (f == null) + if (f == null) { fc.setCurrentDirectory(dir); // restore the saved directory - else + } else { fc.setSelectedFile(f); + } } catch (Exception e) { } fc.addChoosableFileFilter(new GpxFileFilter(true)); int returnVal = fc.showSaveDialog(MainGUI.getMainGUI()); - if (returnVal != JFileChooser.APPROVE_OPTION) + if (returnVal != JFileChooser.APPROVE_OPTION) { return null; + } Settings.getInstance().gpxFileChooserDir = fc.getCurrentDirectory().getAbsolutePath(); return fc.getSelectedFile(); } diff --git a/src/main/java/mobac/gui/actions/HelpLicenses.java b/mobac/src/main/java/mobac/gui/actions/HelpLicenses.java similarity index 90% rename from src/main/java/mobac/gui/actions/HelpLicenses.java rename to mobac/src/main/java/mobac/gui/actions/HelpLicenses.java index c5ba9bd..29243dc 100644 --- a/src/main/java/mobac/gui/actions/HelpLicenses.java +++ b/mobac/src/main/java/mobac/gui/actions/HelpLicenses.java @@ -1,26 +1,26 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; +import mobac.gui.dialogs.LicensesDialog; + import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import mobac.gui.dialogs.LicensesDialog; - public class HelpLicenses implements ActionListener { public void actionPerformed(ActionEvent e) { diff --git a/src/main/java/mobac/gui/actions/OpenInWebbrowser.java b/mobac/src/main/java/mobac/gui/actions/OpenInWebbrowser.java similarity index 89% rename from src/main/java/mobac/gui/actions/OpenInWebbrowser.java rename to mobac/src/main/java/mobac/gui/actions/OpenInWebbrowser.java index dfe0bc1..60e663c 100644 --- a/src/main/java/mobac/gui/actions/OpenInWebbrowser.java +++ b/mobac/src/main/java/mobac/gui/actions/OpenInWebbrowser.java @@ -1,21 +1,23 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; +import mobac.program.Logging; + import java.awt.Desktop; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -25,8 +27,6 @@ import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; -import mobac.program.Logging; - public class OpenInWebbrowser implements ActionListener, MouseListener { URI uri; @@ -47,7 +47,7 @@ public class OpenInWebbrowser implements ActionListener, MouseListener { try { desktop.browse(uri); } catch (IOException e) { - Logging.LOG.error("Failed to open web browser",e); + Logging.LOG.error("Failed to open web browser", e); } } } diff --git a/src/main/java/mobac/gui/actions/PanelShowHide.java b/mobac/src/main/java/mobac/gui/actions/PanelShowHide.java similarity index 88% rename from src/main/java/mobac/gui/actions/PanelShowHide.java rename to mobac/src/main/java/mobac/gui/actions/PanelShowHide.java index b0c3144..47c64a5 100644 --- a/src/main/java/mobac/gui/actions/PanelShowHide.java +++ b/mobac/src/main/java/mobac/gui/actions/PanelShowHide.java @@ -1,36 +1,34 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; +import javax.swing.JPanel; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import javax.swing.JPanel; - public class PanelShowHide implements ActionListener { - private JPanel panel; - + private final JPanel panel; + public PanelShowHide(JPanel panel) { super(); this.panel = panel; } - public void actionPerformed(ActionEvent e) { panel.setVisible(!panel.isVisible()); } diff --git a/mobac/src/main/java/mobac/gui/actions/RefreshCustomMapsources.java b/mobac/src/main/java/mobac/gui/actions/RefreshCustomMapsources.java new file mode 100644 index 0000000..dec9abf --- /dev/null +++ b/mobac/src/main/java/mobac/gui/actions/RefreshCustomMapsources.java @@ -0,0 +1,245 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.gui.actions; + +import jakarta.xml.bind.JAXBException; +import mobac.exceptions.MapSourceCreateException; +import mobac.exceptions.MapSourceInitializationException; +import mobac.gui.MainGUI; +import mobac.mapsources.MapSourcesManager; +import mobac.mapsources.loader.CustomMapSourceLoader; +import mobac.program.interfaces.FileBasedMapSource; +import mobac.program.interfaces.MapSource; +import mobac.program.model.MapSourceLoaderInfo; +import mobac.program.model.MapSourceLoaderInfo.LoaderType; +import mobac.program.model.Settings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.SAXException; + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.AbstractTableModel; +import java.awt.HeadlessException; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class RefreshCustomMapsources implements ActionListener { + + private static final String[] COL_NAMES = new String[]{"Map name", "File path", "Status", "Restart required"}; + private final Logger log = LoggerFactory.getLogger(RefreshCustomMapsources.class); + + public static void main(String[] args) { + List list = new ArrayList<>(); + list.add(new ReloadTableEntry("name", "path", "status", false)); + ReloadInfoDialog dialog = new ReloadInfoDialog(list); + dialog.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } + + public void actionPerformed(ActionEvent event) { + MapSourcesManager manager = MapSourcesManager.getInstance(); + MainGUI gui = MainGUI.getMainGUI(); + MapSource selectedMapSource = gui.getSelectedMapSource(); + boolean updateGui = false; + int count = 0; + + List entries = new ArrayList<>(); + File mapSourcesDir = Settings.getInstance().getMapSourcesDirectory(); + Path mapSourcesDirPath = mapSourcesDir.toPath(); + CustomMapSourceLoader cmsl = new CustomMapSourceLoader(manager, mapSourcesDir); + List newFileList = cmsl.getMapSourceFiles(); + + Set addedFiles = new HashSet<>(newFileList); + for (MapSource ms : manager.getAllAvailableMapSources()) { + if ((ms.getLoaderInfo() == null) || (ms.getLoaderInfo().getSourceFile() == null)) { + continue; + } + addedFiles.remove(ms.getLoaderInfo().getSourceFile()); + } + + for (final MapSource mapSource : manager.getAllAvailableMapSources()) { + String relPath = ""; + if (mapSource.getLoaderInfo() != null) { + MapSourceLoaderInfo loaderInfo = mapSource.getLoaderInfo(); + if (loaderInfo.getLoaderType() == LoaderType.MAPPACK) { + continue; // skip map sources from map packs + } + if (loaderInfo.getSourceFile() != null) { + relPath = mapSourcesDirPath.relativize(loaderInfo.getSourceFile().toPath()).toString(); + } + } + try { + boolean reloaded = false; + boolean dataRefreshed = false; + try { + reloaded = cmsl.reloadCustomMapSource(mapSource); + } catch (MapSourceCreateException | JAXBException | IOException | SAXException + | MapSourceInitializationException e) { + log.error("Failed to reload map source: " + e.getMessage(), e); + } + if (mapSource instanceof FileBasedMapSource) { + FileBasedMapSource fbms = (FileBasedMapSource) mapSource; + fbms.reinitialize(); + dataRefreshed = true; + } + if (reloaded || dataRefreshed) { + count++; + if (mapSource.equals(selectedMapSource)) { + updateGui = true; + } + } + String status = ""; + if (reloaded) { + status = "reloaded"; + } + if (dataRefreshed) { + if (status.length() > 0) { + status += " & "; + } + status += "data refreshed"; + } + if (status.length() == 0) { + status = "unchanged"; + } + entries.add(new ReloadTableEntry(mapSource.getName(), relPath, status, false)); + } catch (Exception e) { + entries.add(new ReloadTableEntry(mapSource.getName(), relPath, "Reloading failed: " + e.getMessage(), + true)); + } + } + for (File f : addedFiles) { + String relPath = mapSourcesDirPath.relativize(f.toPath()).toString(); + try { + MapSource addedMapSource = cmsl.loadCustomMapSource(f); + if (addedMapSource != null) { + entries.add(new ReloadTableEntry(addedMapSource.getName(), relPath, "New file", false)); + manager.addMapSource(addedMapSource); + updateGui = true; + } + } catch (Exception e) { + log.error("Failed to load map source " + f, e); + entries.add(new ReloadTableEntry("?", relPath, "New file", true)); + } + } + + Collections.sort(entries); + new ReloadInfoDialog(entries); + + if (updateGui) { + /* + * The currently selected map source was updated - we have to force an GUI + * update in case the available zoom levels has been changed + */ + gui.updateMapSourcesList(); + gui.mapSourceChanged(selectedMapSource); + } + // JOptionPane.showMessageDialog(gui, + // String.format(I18nUtils.localizedStringForKey("msg_refresh_all_map_source_done"), + // count)); + } + + private static class ReloadInfoDialog extends JFrame { + + public ReloadInfoDialog(List entries) throws HeadlessException { + super("Reloaded map sources"); + final JTable table = new JTable(new ReloadTableModel(entries)); + table.setFillsViewportHeight(true); + // table.setPreferredScrollableViewportSize(new Dimension(500, 70)); + // table.setFillsViewportHeight(true); + // setLayout(new BorderLayout()); + + JScrollPane scrollPane = new JScrollPane(table); + add(scrollPane); + + pack(); + setVisible(true); + } + + } + + private static class ReloadTableModel extends AbstractTableModel { + + final List entries; + + public ReloadTableModel(List entries) { + super(); + this.entries = entries; + } + + @Override + public int getRowCount() { + return entries.size(); + } + + @Override + public int getColumnCount() { + return COL_NAMES.length; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + ReloadTableEntry entry = entries.get(rowIndex); + switch (columnIndex) { + case 0 : + return entry.name; + case 1 : + return entry.relativeFilePath; + case 2 : + return entry.status; + case 3 : + return entry.restartRequired ? "yes" : "no"; + } + return null; + } + + @Override + public String getColumnName(int column) { + return COL_NAMES[column]; + } + + } + + private static class ReloadTableEntry implements Comparable { + public final String name; + public final String relativeFilePath; + public final String status; + public boolean restartRequired; + + public ReloadTableEntry(String name, String relativeFilePath, String status, boolean restartRequired) { + super(); + this.name = name; + this.relativeFilePath = relativeFilePath; + this.status = status; + this.restartRequired = restartRequired; + } + + @Override + public int compareTo(ReloadTableEntry o) { + return relativeFilePath.compareTo(o.relativeFilePath); + } + + } +} diff --git a/src/main/java/mobac/gui/actions/SelectionModeCircle.java b/mobac/src/main/java/mobac/gui/actions/SelectionModeCircle.java similarity index 91% rename from src/main/java/mobac/gui/actions/SelectionModeCircle.java rename to mobac/src/main/java/mobac/gui/actions/SelectionModeCircle.java index 7c712e0..5fe92b5 100644 --- a/src/main/java/mobac/gui/actions/SelectionModeCircle.java +++ b/mobac/src/main/java/mobac/gui/actions/SelectionModeCircle.java @@ -1,28 +1,28 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - import mobac.gui.MainGUI; import mobac.gui.mapview.PreviewMap; import mobac.gui.mapview.controller.PolygonCircleSelectionMapController; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + public class SelectionModeCircle implements ActionListener { public void actionPerformed(ActionEvent e) { diff --git a/src/main/java/mobac/gui/actions/SelectionModePolygon.java b/mobac/src/main/java/mobac/gui/actions/SelectionModePolygon.java similarity index 91% rename from src/main/java/mobac/gui/actions/SelectionModePolygon.java rename to mobac/src/main/java/mobac/gui/actions/SelectionModePolygon.java index 60029e6..d45e774 100644 --- a/src/main/java/mobac/gui/actions/SelectionModePolygon.java +++ b/mobac/src/main/java/mobac/gui/actions/SelectionModePolygon.java @@ -1,28 +1,28 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - import mobac.gui.MainGUI; import mobac.gui.mapview.PreviewMap; import mobac.gui.mapview.controller.PolygonSelectionMapController; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + public class SelectionModePolygon implements ActionListener { public void actionPerformed(ActionEvent e) { diff --git a/src/main/java/mobac/gui/actions/SelectionModeRectangle.java b/mobac/src/main/java/mobac/gui/actions/SelectionModeRectangle.java similarity index 91% rename from src/main/java/mobac/gui/actions/SelectionModeRectangle.java rename to mobac/src/main/java/mobac/gui/actions/SelectionModeRectangle.java index 3d06605..2f00518 100644 --- a/src/main/java/mobac/gui/actions/SelectionModeRectangle.java +++ b/mobac/src/main/java/mobac/gui/actions/SelectionModeRectangle.java @@ -1,28 +1,28 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - import mobac.gui.MainGUI; import mobac.gui.mapview.PreviewMap; import mobac.gui.mapview.controller.RectangleSelectionMapController; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + public class SelectionModeRectangle implements ActionListener { public void actionPerformed(ActionEvent e) { diff --git a/mobac/src/main/java/mobac/gui/actions/SettingsButtonListener.java b/mobac/src/main/java/mobac/gui/actions/SettingsButtonListener.java new file mode 100644 index 0000000..fd9ee69 --- /dev/null +++ b/mobac/src/main/java/mobac/gui/actions/SettingsButtonListener.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.gui.actions; + +import mobac.gui.MainGUI; +import mobac.gui.settings.SettingsGUI; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class SettingsButtonListener implements ActionListener { + + @Override + public void actionPerformed(ActionEvent arg0) { + MainGUI mg = MainGUI.getMainGUI(); + SettingsGUI.showSettingsDialog(mg); + } +} diff --git a/src/main/java/mobac/gui/actions/ShowAboutDialog.java b/mobac/src/main/java/mobac/gui/actions/ShowAboutDialog.java similarity index 90% rename from src/main/java/mobac/gui/actions/ShowAboutDialog.java rename to mobac/src/main/java/mobac/gui/actions/ShowAboutDialog.java index 7f14467..3090b11 100644 --- a/src/main/java/mobac/gui/actions/ShowAboutDialog.java +++ b/mobac/src/main/java/mobac/gui/actions/ShowAboutDialog.java @@ -1,26 +1,26 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; +import mobac.gui.dialogs.AboutDialog; + import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import mobac.gui.dialogs.AboutDialog; - public class ShowAboutDialog implements ActionListener { public void actionPerformed(ActionEvent e) { diff --git a/src/main/java/mobac/gui/actions/ShowHelpAction.java b/mobac/src/main/java/mobac/gui/actions/ShowHelpAction.java similarity index 89% rename from src/main/java/mobac/gui/actions/ShowHelpAction.java rename to mobac/src/main/java/mobac/gui/actions/ShowHelpAction.java index e8a48a3..4d2ef14 100644 --- a/src/main/java/mobac/gui/actions/ShowHelpAction.java +++ b/mobac/src/main/java/mobac/gui/actions/ShowHelpAction.java @@ -1,26 +1,25 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - import mobac.gui.dialogs.Help; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; public class ShowHelpAction implements ActionListener { public void actionPerformed(ActionEvent event) { diff --git a/src/main/java/mobac/gui/actions/ShowReadme.java b/mobac/src/main/java/mobac/gui/actions/ShowReadme.java similarity index 80% rename from src/main/java/mobac/gui/actions/ShowReadme.java rename to mobac/src/main/java/mobac/gui/actions/ShowReadme.java index 6e19d5a..4047585 100644 --- a/src/main/java/mobac/gui/actions/ShowReadme.java +++ b/mobac/src/main/java/mobac/gui/actions/ShowReadme.java @@ -1,43 +1,41 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.actions; -import java.awt.Desktop; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import java.io.IOException; - -import javax.swing.JOptionPane; - import mobac.gui.MainGUI; import mobac.program.DirectoryManager; import mobac.utilities.GUIExceptionHandler; import mobac.utilities.I18nUtils; +import javax.swing.JOptionPane; +import java.awt.Desktop; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.IOException; + public class ShowReadme implements ActionListener { public void actionPerformed(ActionEvent event) { - File readme = new File(DirectoryManager.programDir, "README.HTM"); + File readme = new File(DirectoryManager.programDir, "README.html"); if (!readme.isFile()) { - JOptionPane.showMessageDialog(MainGUI.getMainGUI(), - I18nUtils.localizedStringForKey("msg_no_found_readme_file"), - I18nUtils.localizedStringForKey("Error"), - JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(MainGUI.getMainGUI(), + I18nUtils.localizedStringForKey("msg_no_found_readme_file"), + I18nUtils.localizedStringForKey("Error"), JOptionPane.ERROR_MESSAGE); return; } try { diff --git a/mobac/src/main/java/mobac/gui/actions/SplitPaneHideLeftComponent.java b/mobac/src/main/java/mobac/gui/actions/SplitPaneHideLeftComponent.java new file mode 100644 index 0000000..1c03f49 --- /dev/null +++ b/mobac/src/main/java/mobac/gui/actions/SplitPaneHideLeftComponent.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.gui.actions; + +import javax.swing.JSplitPane; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class SplitPaneHideLeftComponent implements ActionListener { + + private final JSplitPane splitPane; + private final Component leftComponent; + private int dividerSize = 0; + + public SplitPaneHideLeftComponent(JSplitPane splitPane) { + super(); + this.splitPane = splitPane; + this.leftComponent = splitPane.getLeftComponent(); + } + + public void actionPerformed(ActionEvent e) { + if (splitPane.getLeftComponent() == null) { + // show left panel + splitPane.setLeftComponent(leftComponent); + splitPane.setDividerSize(dividerSize); + } else { + // hide left panel + dividerSize = splitPane.getDividerSize(); + leftComponent.setPreferredSize(new Dimension(leftComponent.getWidth(), 100)); + splitPane.setDividerSize(0); + splitPane.setLeftComponent(null); + } + splitPane.revalidate(); + } + +} diff --git a/src/main/java/mobac/gui/atlastree/DragDropController.java b/mobac/src/main/java/mobac/gui/atlastree/DragDropController.java similarity index 83% rename from src/main/java/mobac/gui/atlastree/DragDropController.java rename to mobac/src/main/java/mobac/gui/atlastree/DragDropController.java index 351f994..70d6fcd 100644 --- a/src/main/java/mobac/gui/atlastree/DragDropController.java +++ b/mobac/src/main/java/mobac/gui/atlastree/DragDropController.java @@ -1,21 +1,33 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.atlastree; +import mobac.exceptions.InvalidNameException; +import mobac.program.interfaces.LayerInterface; +import mobac.program.interfaces.MapInterface; +import mobac.program.model.AtlasTreeModel; +import mobac.utilities.I18nUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.JOptionPane; +import javax.swing.JTree; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; import java.awt.HeadlessException; import java.awt.Point; import java.awt.datatransfer.Transferable; @@ -35,23 +47,10 @@ import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; -import javax.swing.JOptionPane; -import javax.swing.JTree; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; - -import mobac.exceptions.InvalidNameException; -import mobac.program.interfaces.LayerInterface; -import mobac.program.interfaces.MapInterface; -import mobac.program.model.AtlasTreeModel; -import mobac.utilities.I18nUtils; - -import org.apache.log4j.Logger; - - public class DragDropController { - static Logger log = Logger.getLogger(DragDropController.class); + private static final Logger log = LoggerFactory.getLogger(DragDropController.class); + JAtlasTree atlasTree; public DragDropController(JAtlasTree atlasTree) { super(); @@ -60,8 +59,6 @@ public class DragDropController { new AtlasDropTarget(); } - JAtlasTree atlasTree; - protected class AtlasDragSource implements DragSourceListener, DragGestureListener { final DragGestureRecognizer recognizer; @@ -69,18 +66,19 @@ public class DragDropController { public AtlasDragSource() { source = new DragSource(); - recognizer = source.createDefaultDragGestureRecognizer(atlasTree, - DnDConstants.ACTION_MOVE, this); + recognizer = source.createDefaultDragGestureRecognizer(atlasTree, DnDConstants.ACTION_MOVE, this); } public void dragGestureRecognized(DragGestureEvent dge) { TreePath path = atlasTree.getSelectionPath(); - if ((path == null) || (path.getPathCount() <= 1)) + if ((path == null) || (path.getPathCount() == 1)) { // We can't move the root node or an empty selection return; + } TreeNode oldNode = (TreeNode) path.getLastPathComponent(); - if (!(oldNode instanceof LayerInterface || oldNode instanceof MapInterface)) + if (!(oldNode instanceof LayerInterface || oldNode instanceof MapInterface)) { return; + } Transferable transferable = new NodeTransferWrapper(oldNode); source.startDrag(dge, DragSource.DefaultMoveNoDrop, transferable, this); } @@ -131,8 +129,7 @@ public class DragDropController { dtde.acceptDrag(dtde.getDropAction()); return; } - if (o instanceof MapInterface && node instanceof LayerInterface - || node instanceof MapInterface) { + if (o instanceof MapInterface && node instanceof LayerInterface || node instanceof MapInterface) { dtde.acceptDrag(dtde.getDropAction()); return; } @@ -147,8 +144,8 @@ public class DragDropController { public synchronized void drop(DropTargetDropEvent dtde) { try { - TreeNode sourceNode = (TreeNode) dtde.getTransferable().getTransferData( - NodeTransferWrapper.ATLAS_OBJECT_FLAVOR); + TreeNode sourceNode = (TreeNode) dtde.getTransferable() + .getTransferData(NodeTransferWrapper.ATLAS_OBJECT_FLAVOR); Point pt = dtde.getLocation(); DropTargetContext dtc = dtde.getDropTargetContext(); @@ -161,17 +158,19 @@ public class DragDropController { return; } AtlasTreeModel atlasTreeModel = (AtlasTreeModel) atlasTree.getModel(); - if (sourceNode instanceof LayerInterface && targetNode instanceof LayerInterface) - mergeLayers(atlasTreeModel, (LayerInterface) sourceNode, - (LayerInterface) targetNode); + if (sourceNode instanceof LayerInterface && targetNode instanceof LayerInterface) { + mergeLayers(atlasTreeModel, (LayerInterface) sourceNode, (LayerInterface) targetNode); + } - if (targetNode instanceof MapInterface) + if (targetNode instanceof MapInterface) { // We can not make a map child of another map // -> use it's layer instead targetNode = targetNode.getParent(); + } - if (sourceNode instanceof MapInterface && targetNode instanceof LayerInterface) + if (sourceNode instanceof MapInterface && targetNode instanceof LayerInterface) { moveMap(atlasTreeModel, (MapInterface) sourceNode, (LayerInterface) targetNode); + } } catch (Exception e) { log.error("", e); @@ -183,24 +182,23 @@ public class DragDropController { protected void mergeLayers(AtlasTreeModel atlasTreeModel, LayerInterface sourceLayer, LayerInterface targetLayer) throws InvalidNameException { int answer = JOptionPane.showConfirmDialog(null, - String.format(I18nUtils.localizedStringForKey("msg_confirm_merge_layer"), - sourceLayer.getName(), targetLayer.getName()), - I18nUtils.localizedStringForKey("msg_confirm_merge_layer_title"), - JOptionPane.YES_NO_OPTION); - if (answer != JOptionPane.YES_OPTION) + String.format(I18nUtils.localizedStringForKey("msg_confirm_merge_layer"), sourceLayer.getName(), + targetLayer.getName()), + I18nUtils.localizedStringForKey("msg_confirm_merge_layer_title"), JOptionPane.YES_NO_OPTION); + if (answer != JOptionPane.YES_OPTION) { return; + } try { atlasTreeModel.mergeLayers(sourceLayer, targetLayer); } catch (InvalidNameException e) { - JOptionPane.showMessageDialog(null, e.getMessage(), - I18nUtils.localizedStringForKey("msg_merge_layer_failed"), - JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(null, e.getMessage(), + I18nUtils.localizedStringForKey("msg_merge_layer_failed"), JOptionPane.ERROR_MESSAGE); throw e; } } - protected void moveMap(AtlasTreeModel atlasTreeModel, MapInterface map, - LayerInterface targetLayer) throws InvalidNameException { + protected void moveMap(AtlasTreeModel atlasTreeModel, MapInterface map, LayerInterface targetLayer) + throws InvalidNameException { atlasTreeModel.moveMap(map, targetLayer); } diff --git a/src/main/java/mobac/gui/atlastree/JAtlasTree.java b/mobac/src/main/java/mobac/gui/atlastree/JAtlasTree.java similarity index 84% rename from src/main/java/mobac/gui/atlastree/JAtlasTree.java rename to mobac/src/main/java/mobac/gui/atlastree/JAtlasTree.java index e311281..e59b0be 100644 --- a/src/main/java/mobac/gui/atlastree/JAtlasTree.java +++ b/mobac/src/main/java/mobac/gui/atlastree/JAtlasTree.java @@ -1,44 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.atlastree; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Rectangle; -import java.awt.dnd.Autoscroll; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; - -import javax.swing.AbstractAction; -import javax.swing.ActionMap; -import javax.swing.InputMap; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JComponent; -import javax.swing.JMenuItem; -import javax.swing.JOptionPane; -import javax.swing.JPopupMenu; -import javax.swing.JTree; -import javax.swing.KeyStroke; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; -import javax.swing.tree.TreeSelectionModel; - import mobac.gui.MainGUI; import mobac.gui.mapview.PreviewMap; import mobac.gui.mapview.layer.MapAreaHighlightingLayer; @@ -59,42 +36,60 @@ import mobac.program.model.TileImageParameters; import mobac.utilities.GUIExceptionHandler; import mobac.utilities.I18nUtils; import mobac.utilities.jdbc.SQLiteLoader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Logger; +import javax.swing.AbstractAction; +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPopupMenu; +import javax.swing.JTree; +import javax.swing.KeyStroke; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.dnd.Autoscroll; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; public class JAtlasTree extends JTree implements Autoscroll { private static final long serialVersionUID = 1L; private static final int margin = 12; - private static final String MSG_ATLAS_VERSION_MISMATCH = I18nUtils.localizedStringForKey("msg_atlas_version_mismatch"); + private static final String MSG_ATLAS_VERSION_MISMATCH = I18nUtils + .localizedStringForKey("msg_atlas_version_mismatch"); - private static final String MSG_ATLAS_DATA_CHECK_FAILED = I18nUtils.localizedStringForKey("msg_atlas_data_check_failed"); + private static final String MSG_ATLAS_DATA_CHECK_FAILED = I18nUtils + .localizedStringForKey("msg_atlas_data_check_failed"); private static final String MSG_ATLAS_EMPTY = I18nUtils.localizedStringForKey("msg_atlas_is_empty"); private static final String ACTION_DELETE_NODE = "DELETE_NODE"; - private static final Logger log = Logger.getLogger(JAtlasTree.class); - - private AtlasTreeModel treeModel; - - private PreviewMap mapView; - + private static final Logger log = LoggerFactory.getLogger(JAtlasTree.class); + private final AtlasTreeModel treeModel; + private final PreviewMap mapView; protected NodeRenderer nodeRenderer; - protected String defaultToolTiptext; - protected KeyStroke deleteNodeKS; - protected DragDropController ddc; - protected boolean displaySelectedMapArea = false; public JAtlasTree(PreviewMap mapView) { super(new AtlasTreeModel()); - if (mapView == null) + if (mapView == null) { throw new NullPointerException("MapView parameter is null"); + } this.mapView = mapView; getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); ddc = new DragDropController(this); @@ -114,24 +109,26 @@ public class JAtlasTree extends JTree implements Autoscroll { // map moving inputMap.put(deleteNodeKS = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), ACTION_DELETE_NODE); - actionMap.put(ACTION_DELETE_NODE, new AbstractAction(I18nUtils.localizedStringForKey("lp_atlas_pop_menu_delete_node")) { + actionMap.put(ACTION_DELETE_NODE, + new AbstractAction(I18nUtils.localizedStringForKey("lp_atlas_pop_menu_delete_node")) { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public void actionPerformed(ActionEvent e) { - deleteSelectedNode(); - JAtlasTree.this.mapView.repaint(); - } + public void actionPerformed(ActionEvent e) { + deleteSelectedNode(); + JAtlasTree.this.mapView.repaint(); + } - }); + }); } public boolean testAtlasContentValid() { AtlasInterface atlas = getAtlas(); if (RequiresSQLite.class.isAssignableFrom(atlas.getOutputFormat().getMapCreatorClass())) { - if (!SQLiteLoader.loadSQLiteOrShowError()) + if (!SQLiteLoader.loadSQLiteOrShowError()) { return false; + } } if (atlas.calculateTilesToDownload() == 0) { JOptionPane.showMessageDialog(null, "" + MSG_ATLAS_EMPTY + "", "Error - atlas has no content", @@ -143,12 +140,14 @@ public class JAtlasTree extends JTree implements Autoscroll { @Override public String getToolTipText(MouseEvent event) { - if (getRowForLocation(event.getX(), event.getY()) == -1) + if (getRowForLocation(event.getX(), event.getY()) == -1) { return defaultToolTiptext; + } TreePath curPath = getPathForLocation(event.getX(), event.getY()); Object o = curPath.getLastPathComponent(); - if (o == null || !(o instanceof ToolTipProvider)) + if (!(o instanceof ToolTipProvider)) { return null; + } return ((ToolTipProvider) o).getToolTip(); } @@ -182,19 +181,21 @@ public class JAtlasTree extends JTree implements Autoscroll { * Changes the atlas format */ public void convertAtlas(AtlasOutputFormat format) { - log.debug("Converting the atlas format to " + format); + log.debug("Converting the atlas format to {}", format); treeModel.getAtlas().setOutputFormat(format); } public void deleteSelectedNode() { TreePath path = getSelectionPath(); - if (path == null) + if (path == null) { return; + } TreeNode selected = (TreeNode) path.getLastPathComponent(); int[] selectedRows = getSelectionRows(); - if (!(selected instanceof CapabilityDeletable)) + if (!(selected instanceof CapabilityDeletable)) { return; + } treeModel.notifyNodeDelete(selected); ((CapabilityDeletable) selected).delete(); @@ -216,7 +217,7 @@ public class JAtlasTree extends JTree implements Autoscroll { } public boolean load(Profile profile) { - log.debug("Loading profile " + profile); + log.debug("Loading profile {}", profile); try { treeModel.load(profile); if (treeModel.getAtlas() instanceof Atlas) { @@ -257,8 +258,9 @@ public class JAtlasTree extends JTree implements Autoscroll { if (selPath != null) { // not clicked on empty area final Object o = selPath.getLastPathComponent(); - if (o == null) + if (o == null) { return; + } if (o instanceof ToolTipProvider) { mi = new JMenuItem(I18nUtils.localizedStringForKey("lp_atlas_pop_menu_show_detail")); mi.addActionListener(new ActionListener() { @@ -270,16 +272,17 @@ public class JAtlasTree extends JTree implements Autoscroll { pm.add(mi); } if (o instanceof AtlasObject) { - final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem(I18nUtils.localizedStringForKey("lp_atlas_pop_menu_display_select_area")); + final JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem( + I18nUtils.localizedStringForKey("lp_atlas_pop_menu_display_select_area")); final MapAreaHighlightingLayer msl = new MapAreaHighlightingLayer(this); cbmi.setSelected(displaySelectedMapArea); cbmi.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (displaySelectedMapArea) { - MapAreaHighlightingLayer.removeHighlightingLayers(); + MapAreaHighlightingLayer.removeHighlightingLayers(mapView); } else { mapView.setSelectionByTileCoordinate(null, null, false); - MapAreaHighlightingLayer.removeHighlightingLayers(); + MapAreaHighlightingLayer.removeHighlightingLayers(mapView); mapView.mapLayers.add(msl); } displaySelectedMapArea = !displaySelectedMapArea; @@ -294,8 +297,8 @@ public class JAtlasTree extends JTree implements Autoscroll { public void actionPerformed(ActionEvent e) { MapInterface map = (MapInterface) o; mapView.setMapSource(map.getMapSource()); - mapView.setSelectionByTileCoordinate(map.getZoom(), map.getMinTileCoordinate(), map - .getMaxTileCoordinate(), true); + mapView.setSelectionByTileCoordinate(map.getZoom(), map.getMinTileCoordinate(), + map.getMaxTileCoordinate(), true); } }); pm.add(mi); @@ -306,8 +309,8 @@ public class JAtlasTree extends JTree implements Autoscroll { MapSelection ms = new MapSelection(map); mapView.setMapSource(map.getMapSource()); mapView.setSelectionAndZoomTo(ms, true); - mapView.setSelectionByTileCoordinate(map.getZoom(), map.getMinTileCoordinate(), map - .getMaxTileCoordinate(), true); + mapView.setSelectionByTileCoordinate(map.getZoom(), map.getMinTileCoordinate(), + map.getMaxTileCoordinate(), true); } }); pm.add(mi); @@ -361,8 +364,9 @@ public class JAtlasTree extends JTree implements Autoscroll { pm.add(mi); } } - if (pm.getComponentCount() > 0) + if (pm.getComponentCount() > 0) { pm.addSeparator(); + } mi = new JMenuItem(I18nUtils.localizedStringForKey("lp_atlas_pop_menu_clear_atals")); mi.addActionListener(new ActionListener() { @@ -397,7 +401,8 @@ public class JAtlasTree extends JTree implements Autoscroll { public void autoscroll(Point cursorLocn) { int realrow = getRowForLocation(cursorLocn.x, cursorLocn.y); Rectangle outer = getBounds(); - realrow = (cursorLocn.y + outer.y <= margin ? realrow < 1 ? 0 : realrow - 1 + realrow = (cursorLocn.y + outer.y <= margin + ? realrow < 1 ? 0 : realrow - 1 : realrow < getRowCount() - 1 ? realrow + 1 : realrow); scrollRowToVisible(realrow); } @@ -405,8 +410,9 @@ public class JAtlasTree extends JTree implements Autoscroll { public Insets getAutoscrollInsets() { Rectangle outer = getBounds(); Rectangle inner = getParent().getBounds(); - return new Insets(inner.y - outer.y + margin, inner.x - outer.x + margin, outer.height - inner.height - inner.y - + outer.y + margin, outer.width - inner.width - inner.x + outer.x + margin); + return new Insets(inner.y - outer.y + margin, inner.x - outer.x + margin, + outer.height - inner.height - inner.y + outer.y + margin, + outer.width - inner.width - inner.x + outer.x + margin); } } diff --git a/src/main/java/mobac/gui/atlastree/MouseController.java b/mobac/src/main/java/mobac/gui/atlastree/MouseController.java similarity index 89% rename from src/main/java/mobac/gui/atlastree/MouseController.java rename to mobac/src/main/java/mobac/gui/atlastree/MouseController.java index 60a301a..4ccecc4 100644 --- a/src/main/java/mobac/gui/atlastree/MouseController.java +++ b/mobac/src/main/java/mobac/gui/atlastree/MouseController.java @@ -1,26 +1,25 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.atlastree; +import javax.swing.tree.TreePath; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import javax.swing.tree.TreePath; - public class MouseController extends MouseAdapter { JAtlasTree atlasTree; @@ -32,11 +31,13 @@ public class MouseController extends MouseAdapter { @Override public void mouseClicked(MouseEvent e) { - if (e.getButton() != MouseEvent.BUTTON1 || e.getClickCount() != 2) + if (e.getButton() != MouseEvent.BUTTON1 || e.getClickCount() != 2) { return; + } TreePath selPath = atlasTree.getSelectionPath(); - if (selPath == null) + if (selPath == null) { return; // clicked on empty area + } atlasTree.selectElementOnMap(selPath.getLastPathComponent()); } diff --git a/src/main/java/mobac/gui/atlastree/NodeEditor.java b/mobac/src/main/java/mobac/gui/atlastree/NodeEditor.java similarity index 87% rename from src/main/java/mobac/gui/atlastree/NodeEditor.java rename to mobac/src/main/java/mobac/gui/atlastree/NodeEditor.java index 417c852..e716b28 100644 --- a/src/main/java/mobac/gui/atlastree/NodeEditor.java +++ b/mobac/src/main/java/mobac/gui/atlastree/NodeEditor.java @@ -1,22 +1,22 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.atlastree; -import java.awt.Component; +import mobac.gui.components.JAtlasNameField; import javax.swing.DefaultCellEditor; import javax.swing.JTree; @@ -24,9 +24,7 @@ import javax.swing.tree.DefaultTreeCellEditor; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreeCellEditor; import javax.swing.tree.TreeCellRenderer; - -import mobac.gui.components.JAtlasNameField; - +import java.awt.Component; public class NodeEditor extends DefaultTreeCellEditor { @@ -36,14 +34,14 @@ public class NodeEditor extends DefaultTreeCellEditor { } @Override - public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, - boolean expanded, boolean leaf, int row) { + public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, boolean expanded, + boolean leaf, int row) { // Each node type has it's own TreeCellRenderer implementation // this not covered by DefaultTreeCellEditor - therefore we have to // correct the renderer each time an editorComponent is requested TreeCellRenderer tcr = tree.getCellRenderer(); - renderer = (DefaultTreeCellRenderer) tcr.getTreeCellRendererComponent(tree, value, - isSelected, expanded, leaf, row, true); + renderer = (DefaultTreeCellRenderer) tcr.getTreeCellRendererComponent(tree, value, isSelected, expanded, leaf, + row, true); return super.getTreeCellEditorComponent(tree, value, isSelected, expanded, leaf, row); } diff --git a/src/main/java/mobac/gui/atlastree/NodeRenderer.java b/mobac/src/main/java/mobac/gui/atlastree/NodeRenderer.java similarity index 87% rename from src/main/java/mobac/gui/atlastree/NodeRenderer.java rename to mobac/src/main/java/mobac/gui/atlastree/NodeRenderer.java index 18f6e86..082c7fc 100644 --- a/src/main/java/mobac/gui/atlastree/NodeRenderer.java +++ b/mobac/src/main/java/mobac/gui/atlastree/NodeRenderer.java @@ -1,33 +1,31 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.atlastree; -import java.awt.Component; +import mobac.program.interfaces.AtlasInterface; +import mobac.program.interfaces.LayerInterface; +import mobac.utilities.Utilities; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JTree; import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.TreeCellRenderer; - -import mobac.program.interfaces.AtlasInterface; -import mobac.program.interfaces.LayerInterface; -import mobac.utilities.Utilities; - +import java.awt.Component; public class NodeRenderer implements TreeCellRenderer { @@ -51,17 +49,17 @@ public class NodeRenderer implements TreeCellRenderer { mapRenderer = new SimpleTreeCellRenderer(mapIcon); } - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, - boolean expanded, boolean leaf, int row, boolean hasFocus) { + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, + boolean leaf, int row, boolean hasFocus) { TreeCellRenderer tcr; if (value instanceof AtlasInterface) { tcr = atlasRenderer; - } else if (value instanceof LayerInterface) + } else if (value instanceof LayerInterface) { tcr = layerRenderer; - else + } else { tcr = mapRenderer; - return tcr.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, - hasFocus); + } + return tcr.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); } protected static class SimpleTreeCellRenderer extends DefaultTreeCellRenderer { diff --git a/src/main/java/mobac/gui/atlastree/NodeTransferWrapper.java b/mobac/src/main/java/mobac/gui/atlastree/NodeTransferWrapper.java similarity index 84% rename from src/main/java/mobac/gui/atlastree/NodeTransferWrapper.java rename to mobac/src/main/java/mobac/gui/atlastree/NodeTransferWrapper.java index b933872..15d2a1b 100644 --- a/src/main/java/mobac/gui/atlastree/NodeTransferWrapper.java +++ b/mobac/src/main/java/mobac/gui/atlastree/NodeTransferWrapper.java @@ -1,45 +1,44 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.atlastree; +import mobac.program.interfaces.AtlasObject; + +import javax.swing.tree.TreeNode; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; -import javax.swing.tree.TreeNode; - -import mobac.program.interfaces.AtlasObject; - - public class NodeTransferWrapper implements Transferable { public static final DataFlavor ATLAS_OBJECT_FLAVOR = new DataFlavor(AtlasObject.class, "AtlasObject"); - public static final DataFlavor[] FLAVORS = new DataFlavor[] { ATLAS_OBJECT_FLAVOR }; + public static final DataFlavor[] FLAVORS = new DataFlavor[]{ATLAS_OBJECT_FLAVOR}; - private TreeNode node; + private final TreeNode node; public NodeTransferWrapper(TreeNode node) { this.node = node; } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { - if (!ATLAS_OBJECT_FLAVOR.equals(flavor)) + if (!ATLAS_OBJECT_FLAVOR.equals(flavor)) { throw new UnsupportedFlavorException(flavor); + } return node; } diff --git a/src/main/java/mobac/gui/components/FilledLayeredPane.java b/mobac/src/main/java/mobac/gui/components/FilledLayeredPane.java similarity index 85% rename from src/main/java/mobac/gui/components/FilledLayeredPane.java rename to mobac/src/main/java/mobac/gui/components/FilledLayeredPane.java index 3898b6e..7095ae9 100644 --- a/src/main/java/mobac/gui/components/FilledLayeredPane.java +++ b/mobac/src/main/java/mobac/gui/components/FilledLayeredPane.java @@ -1,33 +1,31 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; -import java.awt.Component; - import javax.swing.JLayeredPane; +import java.awt.Component; public class FilledLayeredPane extends JLayeredPane { private static final long serialVersionUID = 1L; /** - * Layout each of the components in this JLayeredPane so that they all fill - * the entire extents of the layered pane -- from (0,0) to (getWidth(), - * getHeight()) + * Layout each of the components in this JLayeredPane so that they all fill the + * entire extents of the layered pane -- from (0,0) to (getWidth(), getHeight()) */ @Override public void doLayout() { diff --git a/src/main/java/mobac/gui/components/JAtlasNameField.java b/mobac/src/main/java/mobac/gui/components/JAtlasNameField.java similarity index 89% rename from src/main/java/mobac/gui/components/JAtlasNameField.java rename to mobac/src/main/java/mobac/gui/components/JAtlasNameField.java index df05a03..17702ca 100644 --- a/src/main/java/mobac/gui/components/JAtlasNameField.java +++ b/mobac/src/main/java/mobac/gui/components/JAtlasNameField.java @@ -1,29 +1,27 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; -import javax.swing.JTextField; - import mobac.program.model.Profile; +import javax.swing.JTextField; /** * A {@link JTextField} that only accepts ASCII characters, numbers and spaces. - * */ public class JAtlasNameField extends JRegexTextField { diff --git a/src/main/java/mobac/gui/components/JBookmarkMenuItem.java b/mobac/src/main/java/mobac/gui/components/JBookmarkMenuItem.java similarity index 91% rename from src/main/java/mobac/gui/components/JBookmarkMenuItem.java rename to mobac/src/main/java/mobac/gui/components/JBookmarkMenuItem.java index cd9d5fa..f2e5c2f 100644 --- a/src/main/java/mobac/gui/components/JBookmarkMenuItem.java +++ b/mobac/src/main/java/mobac/gui/components/JBookmarkMenuItem.java @@ -1,29 +1,28 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JMenuItem; - import mobac.gui.MainGUI; import mobac.program.model.Bookmark; +import javax.swing.JMenuItem; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + public class JBookmarkMenuItem extends JMenuItem implements ActionListener { private final Bookmark bookmark; diff --git a/src/main/java/mobac/gui/components/JCollapsiblePanel.java b/mobac/src/main/java/mobac/gui/components/JCollapsiblePanel.java similarity index 84% rename from src/main/java/mobac/gui/components/JCollapsiblePanel.java rename to mobac/src/main/java/mobac/gui/components/JCollapsiblePanel.java index 7d6e3bc..cbc60af 100644 --- a/src/main/java/mobac/gui/components/JCollapsiblePanel.java +++ b/mobac/src/main/java/mobac/gui/components/JCollapsiblePanel.java @@ -1,21 +1,30 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; +import mobac.utilities.GBC; +import mobac.utilities.Utilities; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.border.Border; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -28,33 +37,19 @@ import java.awt.LayoutManager; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.ImageIcon; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.border.Border; - -import mobac.utilities.GBC; -import mobac.utilities.Utilities; - - /** * Bases upon "TitleContainer" from project "swivel" * http://code.google.com/p/swivel/ (LGPL license) - * + *

* A {@code TitleContainer} is a simple container that provides an easily * visible title. - * */ public class JCollapsiblePanel extends JPanel { - private static final long serialVersionUID = 1L; - protected static final int DEFAULT_TITLE_PADDING = 3; protected static final Color DEFAULT_TITLE_BACKGROUND_COLOR = Color.LIGHT_GRAY; protected static final Color DEFAULT_TITLE_COLOR = Color.BLACK; - + private static final long serialVersionUID = 1L; private static ImageIcon arrowClosed; private static ImageIcon arrowOpen; @@ -72,24 +67,12 @@ public class JCollapsiblePanel extends JPanel { protected final JLabel titleIcon; protected final JLabel titleLabel; protected final JPanel titlePanel; - - // main component - protected Container contentContainer; - // collapsing protected final CollapsingMouseListener collapsingMouseListener; + // main component + protected Container contentContainer; private boolean isCollapsed; - /** - * Constructs a {@code TitleContainer} that wraps the specified container. - * - * @param container - * the main container - */ - public JCollapsiblePanel(Container container) { - this(container, ""); - } - public JCollapsiblePanel(String title) { this(new JPanel(), title); } @@ -100,9 +83,9 @@ public class JCollapsiblePanel extends JPanel { } /** - * Constructs a {@code TitleContainer} that wraps the specified component - * and has the specified title. - * + * Constructs a {@code TitleContainer} that wraps the specified component and + * has the specified title. + * * @param container * the main container * @param title @@ -112,7 +95,7 @@ public class JCollapsiblePanel extends JPanel { super(); setName(title); titleIcon = new JLabel(arrowOpen); - titleLabel = new JLabel(title); + titleLabel = new JLabel(title + ":"); titlePanel = new JPanel(new GridBagLayout()); // mainComponentPanel = new JPanel(new GridBagLayout()); collapsingMouseListener = new CollapsingMouseListener(); @@ -129,20 +112,42 @@ public class JCollapsiblePanel extends JPanel { setTitleBarPadding(DEFAULT_TITLE_PADDING); // layout - titlePanel.add(titleIcon, GBC.std()); - titlePanel.add(titleLabel, GBC.std().insets(5, 0, 1, 0)); - titlePanel.add(Box.createHorizontalGlue(), GBC.eol().fill()); + fillTitlePanel(); + + titlePanel.add(Box.createHorizontalGlue(), GBC.std().fill()); setLayout(new BorderLayout()); add(titlePanel, BorderLayout.NORTH); add(container, BorderLayout.CENTER); setContentContainer(container); setBorder(BorderFactory.createEtchedBorder()); + setTitlePanelPreferredSize(); + } + + protected void fillTitlePanel() { + titlePanel.add(titleIcon, GBC.std()); + titlePanel.add(titleLabel, GBC.std().insets(5, 0, 1, 0)); + } + + private void setTitlePanelPreferredSize() { + Dimension containerPreferredDimension = contentContainer.getLayout().preferredLayoutSize(contentContainer); + Dimension titlePanelPreferredDimension = titlePanel.getPreferredSize(); + titlePanel.setPreferredSize( + new Dimension(containerPreferredDimension.width, titlePanelPreferredDimension.height)); + } + + /** + * Gets whether the container is collapsed or not. + * + * @return whether the container is collapsed or not + */ + public boolean isCollapsed() { + return isCollapsed; } /** * This method provides a programmatic way to collapse the container. - * + * * @param collapsed * whether the container should be collapsed or shown */ @@ -156,9 +161,7 @@ public class JCollapsiblePanel extends JPanel { // We have to make sure that the panel width does not shrink because // of the hidden content of contentContainer - Dimension dcont = contentContainer.getLayout().preferredLayoutSize(contentContainer); - Dimension pref = titlePanel.getPreferredSize(); - titlePanel.setPreferredSize(new Dimension(dcont.width, pref.height)); + setTitlePanelPreferredSize(); } else { titleIcon.setIcon(arrowOpen); } @@ -169,17 +172,17 @@ public class JCollapsiblePanel extends JPanel { } /** - * Gets whether the container is collapsed or not. - * - * @return whether the container is collapsed or not + * Gets the this container's title. + * + * @return the title */ - public boolean isCollapsed() { - return isCollapsed; + public String getTitle() { + return titleLabel.getText(); } /** * Sets the title of this container. - * + * * @param title * the title */ @@ -192,17 +195,17 @@ public class JCollapsiblePanel extends JPanel { } /** - * Gets the this container's title. - * - * @return the title + * Gets the main content container for this container. + * + * @return the main container */ - public String getTitle() { - return titleLabel.getText(); + public Container getContentContainer() { + return contentContainer; } /** * Sets the main content container for this container. - * + * * @param container * the main content container */ @@ -225,22 +228,13 @@ public class JCollapsiblePanel extends JPanel { revalidate(); } - /** - * Gets the main content container for this container. - * - * @return the main container - */ - public Container getContentContainer() { - return contentContainer; - } - public void addContent(Component comp, Object constraints) { contentContainer.add(comp, constraints); } /** * Sets the title font. - * + * * @param font * the title font */ @@ -253,7 +247,7 @@ public class JCollapsiblePanel extends JPanel { /** * Sets the background color of the title bar. - * + * * @param color * the color */ @@ -263,7 +257,7 @@ public class JCollapsiblePanel extends JPanel { /** * Sets the title text color. - * + * * @param color * the color */ @@ -273,7 +267,7 @@ public class JCollapsiblePanel extends JPanel { /** * Sets the title bar padding in pixels. - * + * * @param padding * the title bar padding in pixels */ @@ -283,9 +277,18 @@ public class JCollapsiblePanel extends JPanel { } /** - * Sets the visibility of the title bar. If the title bar is invisible, the - * user will not be able to collapse or decollapse the container. - * + * Gets the visibility of the title bar. + * + * @return true if the title bar is visible, false otherwise + */ + public boolean isTitleBarVisible() { + return this.titlePanel.isVisible(); + } + + /** + * Sets the visibility of the title bar. If the title bar is invisible, the user + * will not be able to collapse or decollapse the container. + * * @param visible * visibility of the title bar */ @@ -293,28 +296,19 @@ public class JCollapsiblePanel extends JPanel { this.titlePanel.setVisible(visible); } - /** - * Gets the visibility of the title bar. - * - * @return true if the title bar is visible, false otherwise - */ - public boolean isTitleBarVisible() { - return this.titlePanel.isVisible(); - } - - //-------------------------------------------------------------------------- + // -------------------------------------------------------------------------- /** - * A {@code MouseListener} that changes the cursor when moved over the title - * bar to indicate that it is clickable. Clicking the title bar collapses - * the container. + * A {@code MouseListener} that changes the cursor when moved over the title bar + * to indicate that it is clickable. Clicking the title bar collapses the + * container. */ private class CollapsingMouseListener extends MouseAdapter { private final Cursor CLICK_ME_CURSOR = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); /** * Collapses or shows the titled component. - * + *

* {@inheritDoc} */ public void mousePressed(MouseEvent e) { @@ -323,7 +317,7 @@ public class JCollapsiblePanel extends JPanel { /** * Changes the cursor to indicate clickability. - * + *

* {@inheritDoc} */ public void mouseEntered(MouseEvent e) { @@ -332,7 +326,7 @@ public class JCollapsiblePanel extends JPanel { /** * Changes the cursor back to the default. - * + *

* {@inheritDoc} */ public void mouseExited(MouseEvent e) { diff --git a/src/main/java/mobac/gui/components/JCoordinateField.java b/mobac/src/main/java/mobac/gui/components/JCoordinateField.java similarity index 84% rename from src/main/java/mobac/gui/components/JCoordinateField.java rename to mobac/src/main/java/mobac/gui/components/JCoordinateField.java index 6a55d85..c7892b6 100644 --- a/src/main/java/mobac/gui/components/JCoordinateField.java +++ b/mobac/src/main/java/mobac/gui/components/JCoordinateField.java @@ -1,21 +1,28 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; +import mobac.utilities.I18nUtils; +import mobac.utilities.Utilities; +import mobac.utilities.geo.CoordinateDms2Format; + +import javax.swing.JTextField; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; import java.awt.Color; import java.awt.Point; import java.awt.event.MouseEvent; @@ -24,14 +31,6 @@ import java.text.NumberFormat; import java.text.ParseException; import java.text.ParsePosition; -import javax.swing.JTextField; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -import mobac.utilities.I18nUtils; -import mobac.utilities.Utilities; -import mobac.utilities.geo.CoordinateDms2Format; - public class JCoordinateField extends JTextField { private static final long serialVersionUID = 1L; @@ -39,14 +38,11 @@ public class JCoordinateField extends JTextField { private static final Color ERROR_COLOR = new Color(255, 100, 100); private static final String INVALID_TEXT = I18nUtils.localizedStringForKey("lp_coords_invalid_text"); - - private JCoordinateListener coordinateListener; - private boolean inputIsValid = true; - - private NumberFormat numberFormat; - private final double min; private final double max; + private final JCoordinateListener coordinateListener; + private boolean inputIsValid = true; + private NumberFormat numberFormat; public JCoordinateField(double min, double max) { super(10); @@ -59,12 +55,24 @@ public class JCoordinateField extends JTextField { @Override public Point getToolTipLocation(MouseEvent event) { - if (getToolTipText().length() > 0) + if (getToolTipText().length() > 0) { return super.getToolTipLocation(event); - else - // We don't want a tool tip but Java does not allow to disable it? - // -> show it at a point where no user will ever see it + } else + // We don't want a tool tip but Java does not allow to disable it? + // -> show it at a point where no user will ever see it + { return new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + } + + public double getCoordinate() throws ParseException { + ParsePosition pos = new ParsePosition(0); + String text = JCoordinateField.this.getText(); + Number num = numberFormat.parse(text, pos); + if (num == null || pos.getErrorIndex() >= 0 || Double.isNaN(num.doubleValue())) { + throw new ParseException(text, pos.getErrorIndex()); + } + return num.doubleValue(); } public void setCoordinate(double value) { @@ -79,28 +87,21 @@ public class JCoordinateField extends JTextField { } else { super.setText(numberFormat.format(value)); } - if (newValid != inputIsValid) + if (newValid != inputIsValid) { coordinateListener.changeValidMode(true); + } } finally { coordinateListener.setEnabled(true); } } - public double getCoordinate() throws ParseException { - ParsePosition pos = new ParsePosition(0); - String text = JCoordinateField.this.getText(); - Number num = numberFormat.parse(text, pos); - if (num == null || pos.getErrorIndex() >= 0 || Double.isNaN(num.doubleValue())) - throw new ParseException(text, pos.getErrorIndex()); - return num.doubleValue(); - } - public double getCoordinateOrNaN() { ParsePosition pos = new ParsePosition(0); String text = JCoordinateField.this.getText(); Number num = numberFormat.parse(text, pos); - if (num == null || pos.getErrorIndex() >= 0) + if (num == null || pos.getErrorIndex() >= 0) { return Double.NaN; + } return num.doubleValue(); } @@ -120,7 +121,7 @@ public class JCoordinateField extends JTextField { protected class JCoordinateListener implements DocumentListener { - private Color defaultColor; + private final Color defaultColor; private boolean enabled; @@ -131,8 +132,9 @@ public class JCoordinateField extends JTextField { } private void checkCoordinate(DocumentEvent de) { - if (!enabled) + if (!enabled) { return; + } boolean valid = false; try { ParsePosition pos = new ParsePosition(0); @@ -147,18 +149,21 @@ public class JCoordinateField extends JTextField { } catch (Exception e) { valid = false; } - if (valid != inputIsValid) + if (valid != inputIsValid) { changeValidMode(valid); + } } private void changeValidMode(boolean valid) { Color newC = valid ? defaultColor : ERROR_COLOR; JCoordinateField.this.setBackground(newC); - String toolTip = valid ? "" : String.format(INVALID_TEXT, numberFormat.format(min), - numberFormat.format(max)); + String toolTip = valid + ? "" + : String.format(INVALID_TEXT, numberFormat.format(min), numberFormat.format(max)); JCoordinateField.this.setToolTipText(toolTip); - if (toolTip.length() > 0) + if (toolTip.length() > 0) { Utilities.showTooltipNow(JCoordinateField.this); + } inputIsValid = valid; } diff --git a/src/main/java/mobac/gui/components/JDirectoryChooser.java b/mobac/src/main/java/mobac/gui/components/JDirectoryChooser.java similarity index 86% rename from src/main/java/mobac/gui/components/JDirectoryChooser.java rename to mobac/src/main/java/mobac/gui/components/JDirectoryChooser.java index 446259e..ccb31df 100644 --- a/src/main/java/mobac/gui/components/JDirectoryChooser.java +++ b/mobac/src/main/java/mobac/gui/components/JDirectoryChooser.java @@ -1,27 +1,26 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; -import java.io.File; +import mobac.utilities.I18nUtils; import javax.swing.JFileChooser; import javax.swing.filechooser.FileFilter; - -import mobac.utilities.I18nUtils; +import java.io.File; public class JDirectoryChooser extends JFileChooser { @@ -31,7 +30,7 @@ public class JDirectoryChooser extends JFileChooser { super(); setDialogType(CUSTOM_DIALOG); setDialogTitle(I18nUtils.localizedStringForKey("dlg_select_dir_title")); - //setApproveButtonText("Select Directory"); + // setApproveButtonText("Select Directory"); setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); setAcceptAllFileFilterUsed(false); addChoosableFileFilter(new FileFilter() { @@ -50,8 +49,9 @@ public class JDirectoryChooser extends JFileChooser { @Override public void approveSelection() { - if (!this.getFileFilter().accept(this.getSelectedFile())) + if (!this.getFileFilter().accept(this.getSelectedFile())) { return; + } super.approveSelection(); } diff --git a/src/main/java/mobac/gui/components/JDistanceSlider.java b/mobac/src/main/java/mobac/gui/components/JDistanceSlider.java similarity index 78% rename from src/main/java/mobac/gui/components/JDistanceSlider.java rename to mobac/src/main/java/mobac/gui/components/JDistanceSlider.java index 755f51d..7da30c1 100644 --- a/src/main/java/mobac/gui/components/JDistanceSlider.java +++ b/mobac/src/main/java/mobac/gui/components/JDistanceSlider.java @@ -1,52 +1,49 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; -import java.util.Hashtable; +import mobac.program.interfaces.MapSpace; +import mobac.program.model.UnitSystem; import javax.swing.JLabel; import javax.swing.JSlider; - -import mobac.program.interfaces.MapSpace; -import mobac.program.model.UnitSystem; +import java.util.Hashtable; public class JDistanceSlider extends JSlider { private static final long serialVersionUID = 1L; - private final Hashtable labelTable; - public JDistanceSlider(MapSpace mapSpace, int zoom, int y, UnitSystem unit, int pixelMin, int pixelMax) { super(pixelMin, pixelMax); - labelTable = new Hashtable(); + Hashtable labelTable = new Hashtable<>(); int diff4 = (pixelMax - pixelMin) / 4; - int[] labelvalues = new int[] { pixelMin, pixelMin + diff4, pixelMin + 2 * diff4, pixelMin + 3 * diff4, - pixelMax }; + int[] labelValues = new int[]{pixelMin, pixelMin + diff4, pixelMin + 2 * diff4, pixelMin + 3 * diff4, pixelMax}; - for (int i : labelvalues) { + for (int i : labelValues) { double distance = mapSpace.horizontalDistance(zoom, y, i) * unit.earthRadius * unit.unitFactor; String label; if (distance > unit.unitFactor) { distance /= unit.unitFactor; label = String.format("%2.0f %s", distance, unit.unitLarge); - } else + } else { label = String.format("%2.0f %s", distance, unit.unitSmall); - labelTable.put(new Integer(i), new JLabel(label)); + } + labelTable.put(i, new JLabel(label)); } setPaintTicks(true); setMajorTickSpacing(diff4); diff --git a/src/main/java/mobac/gui/components/JDropDownButton.java b/mobac/src/main/java/mobac/gui/components/JDropDownButton.java similarity index 87% rename from src/main/java/mobac/gui/components/JDropDownButton.java rename to mobac/src/main/java/mobac/gui/components/JDropDownButton.java index fe8a6cf..37393b4 100644 --- a/src/main/java/mobac/gui/components/JDropDownButton.java +++ b/mobac/src/main/java/mobac/gui/components/JDropDownButton.java @@ -1,27 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.JButton; @@ -29,18 +23,22 @@ import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.SwingConstants; import javax.swing.plaf.basic.BasicArrowButton; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; public class JDropDownButton extends JButton { private static final long serialVersionUID = 1L; - private BasicArrowButton arrowButton; - private JPopupMenu buttonPopupMenu; + private final JPopupMenu buttonPopupMenu; public JDropDownButton(String text) { super(text); buttonPopupMenu = new JPopupMenu(); - arrowButton = new BasicArrowButton(SwingConstants.SOUTH, null, null, Color.BLACK, null); + BasicArrowButton arrowButton = new BasicArrowButton(SwingConstants.SOUTH, null, null, Color.BLACK, null); arrowButton.setBorder(BorderFactory.createEmptyBorder()); arrowButton.setFocusable(false); setHorizontalAlignment(SwingConstants.LEFT); diff --git a/src/main/java/mobac/gui/components/JIntCombo.java b/mobac/src/main/java/mobac/gui/components/JIntCombo.java similarity index 85% rename from src/main/java/mobac/gui/components/JIntCombo.java rename to mobac/src/main/java/mobac/gui/components/JIntCombo.java index 05b523a..08e11c8 100644 --- a/src/main/java/mobac/gui/components/JIntCombo.java +++ b/mobac/src/main/java/mobac/gui/components/JIntCombo.java @@ -1,35 +1,35 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.ComboBoxEditor; +import javax.swing.JComboBox; import java.awt.Component; import java.awt.event.ActionListener; import java.util.Vector; -import javax.swing.ComboBoxEditor; -import javax.swing.JComboBox; - -import org.apache.log4j.Logger; - -public class JIntCombo extends JComboBox { +public class JIntCombo extends JComboBox { private static final long serialVersionUID = 1L; - static Logger log = Logger.getLogger(JIntCombo.class); + private static final Logger log = LoggerFactory.getLogger(JIntCombo.class); protected JIntField editorComponent; protected Integer defaultValue; @@ -87,6 +87,13 @@ public class JIntCombo extends JComboBox { } } + public void setItem(Object entry) { + if (entry == null) { + return; + } + editorComponent.setValue(((Integer) entry).intValue(), true); + } + public void removeActionListener(ActionListener l) { editorComponent.removeActionListener(l); } @@ -95,12 +102,6 @@ public class JIntCombo extends JComboBox { editorComponent.selectAll(); } - public void setItem(Object entry) { - if (entry == null) - return; - editorComponent.setValue(((Integer) entry).intValue(), true); - } - } } diff --git a/src/main/java/mobac/gui/components/JIntField.java b/mobac/src/main/java/mobac/gui/components/JIntField.java similarity index 85% rename from src/main/java/mobac/gui/components/JIntField.java rename to mobac/src/main/java/mobac/gui/components/JIntField.java index a8189c4..00b7740 100644 --- a/src/main/java/mobac/gui/components/JIntField.java +++ b/mobac/src/main/java/mobac/gui/components/JIntField.java @@ -1,45 +1,38 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; -import java.awt.Color; +import mobac.program.model.NumericDocument; +import mobac.utilities.Utilities; import javax.swing.JTextField; import javax.swing.border.EmptyBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; - -import mobac.program.model.NumericDocument; -import mobac.utilities.Utilities; - +import java.awt.Color; public class JIntField extends JTextField { private static final long serialVersionUID = 1L; - - protected Color errorColor = new Color(255, 100, 100); - + private final String errorText; + private final InputListener listener; public int min = 0; - public int max = 0; - - private String errorText; - - private InputListener listener; + protected Color errorColor = new Color(255, 100, 100); private boolean inputIsValid = true; public JIntField(int min, int max, int columns, String errorText) { @@ -62,12 +55,14 @@ public class JIntField extends JTextField { } public void setValue(int newValue, boolean check) { - if (newValue <= 0) + if (newValue <= 0) { super.setText(""); - else + } else { super.setText(Integer.toString(newValue)); - if (check) + } + if (check) { listener.checkInput(null); + } } public void setText(String t) { @@ -87,11 +82,9 @@ public class JIntField extends JTextField { } } - - protected class InputListener implements DocumentListener { - private Color defaultColor; + private final Color defaultColor; private InputListener() { defaultColor = JIntField.this.getBackground(); @@ -105,18 +98,20 @@ public class JIntField extends JTextField { } catch (Exception e) { valid = false; } - if (valid != inputIsValid) + if (valid != inputIsValid) { setDisplayedValidMode(valid); + } inputIsValid = valid; } private void setDisplayedValidMode(boolean valid) { Color newC = valid ? defaultColor : errorColor; JIntField.this.setBackground(newC); - String toolTip = valid ? "" : String.format(errorText, new Object[] { min, max }); + String toolTip = valid ? "" : String.format(errorText, min, max); JIntField.this.setToolTipText(toolTip); - if (toolTip.length() > 0) + if (toolTip.length() > 0) { Utilities.showTooltipNow(JIntField.this); + } } public void changedUpdate(DocumentEvent e) { diff --git a/src/main/java/mobac/gui/components/JMapSizeCombo.java b/mobac/src/main/java/mobac/gui/components/JMapSizeCombo.java similarity index 62% rename from src/main/java/mobac/gui/components/JMapSizeCombo.java rename to mobac/src/main/java/mobac/gui/components/JMapSizeCombo.java index 9876dd7..545c459 100644 --- a/src/main/java/mobac/gui/components/JMapSizeCombo.java +++ b/mobac/src/main/java/mobac/gui/components/JMapSizeCombo.java @@ -1,54 +1,50 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.Color; import java.util.Vector; -import org.apache.log4j.Logger; - public class JMapSizeCombo extends JIntCombo { - private static final long serialVersionUID = 1L; - public static final int MIN = 10; - public static final int MAX = Integer.MAX_VALUE; - - static Vector MAP_SIZE_VALUES; - - static Integer DEFAULT; - - static Logger log = Logger.getLogger(JMapSizeCombo.class); + static final Vector MAP_SIZE_VALUES; + static final Integer DEFAULT; + private static final long serialVersionUID = 1L; + private static final Logger log = LoggerFactory.getLogger(JMapSizeCombo.class); static { // Sizes from 1024 to 32768 MAP_SIZE_VALUES = new Vector(11); - MAP_SIZE_VALUES.addElement(new Integer(128000)); - MAP_SIZE_VALUES.addElement(new Integer(1048575)); - MAP_SIZE_VALUES.addElement(new Integer(65536)); - MAP_SIZE_VALUES.addElement(DEFAULT = new Integer(32767)); - MAP_SIZE_VALUES.addElement(new Integer(30000)); - MAP_SIZE_VALUES.addElement(new Integer(25000)); - MAP_SIZE_VALUES.addElement(new Integer(20000)); - MAP_SIZE_VALUES.addElement(new Integer(15000)); - MAP_SIZE_VALUES.addElement(new Integer(10000)); - MAP_SIZE_VALUES.addElement(new Integer(2048)); - MAP_SIZE_VALUES.addElement(new Integer(1024)); + MAP_SIZE_VALUES.addElement(128000); + MAP_SIZE_VALUES.addElement(1048575); + MAP_SIZE_VALUES.addElement(65536); + MAP_SIZE_VALUES.addElement(DEFAULT = 32767); + MAP_SIZE_VALUES.addElement(30000); + MAP_SIZE_VALUES.addElement(25000); + MAP_SIZE_VALUES.addElement(20000); + MAP_SIZE_VALUES.addElement(15000); + MAP_SIZE_VALUES.addElement(10000); + MAP_SIZE_VALUES.addElement(2048); + MAP_SIZE_VALUES.addElement(1024); } public JMapSizeCombo() { diff --git a/mobac/src/main/java/mobac/gui/components/JMapSourceTree.java b/mobac/src/main/java/mobac/gui/components/JMapSourceTree.java new file mode 100644 index 0000000..e5c809a --- /dev/null +++ b/mobac/src/main/java/mobac/gui/components/JMapSourceTree.java @@ -0,0 +1,561 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ + +package mobac.gui.components; + +import mobac.mapsources.AbstractMultiLayerMapSource; +import mobac.program.interfaces.FileBasedMapSource; +import mobac.program.interfaces.HttpMapSource; +import mobac.program.interfaces.MapSource; +import mobac.program.model.MapSourceLoaderInfo; +import mobac.utilities.I18nUtils; +import mobac.utilities.Utilities; +import org.apache.commons.text.StringEscapeUtils; + +import javax.swing.BorderFactory; +import javax.swing.ImageIcon; +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; +import java.io.File; +import java.util.Enumeration; +import java.util.Vector; + +/** + * @author Maksym "elmuSSo" Kondej + *

+ * This class holds methods needed for managing a MapSources loaded into + * a JTree structure + */ +public class JMapSourceTree extends JTree { + + // Specifying a class which will determine if a node is a folder + static final Class folderClass = String.class; + // private final Logger log = LoggerFactory.getLogger(JMapSourceTree.class); + private static final long serialVersionUID = 1L; + private static final Color mapSourceInTreeHighlightColor = new Color(230, 245, 255); + private final ComparableTreeNode rootNode = new ComparableTreeNode("Maps sources root"); + private final DefaultTreeModel treeModel = new DefaultTreeModel(rootNode); + private Vector mapSources; + private MapSource selectedMapSource, previouslySelectedMapSource; + + public JMapSourceTree(Vector enabledOrderedMapSources) { + super(); + // Setting a cell renderer which will provide proper icons behavior + setCellRenderer(new CustomIconRenderer()); + initialize(enabledOrderedMapSources); + setRootVisible(false); + getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + setExpandsSelectedPaths(true); + setToggleClickCount(1); + setToolTipText(I18nUtils.localizedStringForKey("lp_map_source_tree_tips")); + } + + /** + * This method searches for a parentNode's child relying on its name + * + * @param parentNode + * - its children will be iterated during search + * @param nodeName + * - name of a sought node + * @return found child, or null if child was not found + */ + private static ComparableTreeNode getChildByUserObject(ComparableTreeNode parentNode, String nodeName) { + Enumeration childsOfParent = parentNode.breadthFirstEnumeration(); + while (childsOfParent.hasMoreElements()) { + ComparableTreeNode child = (ComparableTreeNode) childsOfParent.nextElement(); + if (child.getUserObject().equals(nodeName)) { + return child; + } + } + return null; + } + + /** + * Static method used for dynamic generation of a tooltip with information about + * a mapSource + * + * @param mapSource + * - of which information will be put into a tooltip + * @return generated tooltip string + */ + public static String generateMapSourceTooltip(MapSource mapSource) { + boolean multiLayer = (mapSource instanceof AbstractMultiLayerMapSource); + boolean fileBased = (mapSource instanceof FileBasedMapSource); + + // Getting a localized string for an input to tooltip + String locName = I18nUtils.localizedStringForKey("lp_map_source_tooltip_layer_name"); + String locInternalName = I18nUtils.localizedStringForKey("lp_map_source_tooltip_inernal_name"); + String locType = I18nUtils.localizedStringForKey("lp_map_source_tooltip_type"); + String locLoadedFrom = I18nUtils.localizedStringForKey("lp_map_source_tooltip_loaded_from"); + String locFileName = I18nUtils.localizedStringForKey("lp_map_source_tooltip_file_name"); + + String locMultiLayer = I18nUtils.localizedStringForKey("lp_map_source_layer_multi"); + String locSingleLayer = I18nUtils.localizedStringForKey("lp_map_source_layer_single"); + String locFileBased = I18nUtils.localizedStringForKey("lp_map_source_layer_file_based"); + String locWebBased = I18nUtils.localizedStringForKey("lp_map_source_layer_web_based"); + + // Getting a values for some attributes + String name = StringEscapeUtils.escapeHtml4(mapSource.toString()); + String nameInternal = StringEscapeUtils.escapeHtml4(mapSource.getName()); + String type1 = multiLayer ? locMultiLayer : locSingleLayer; + String type2 = fileBased ? locFileBased : locWebBased; + + String toolTipString = locName + ": %s
" + locInternalName + ": %s
" + locType + ": %s (%s)"; + toolTipString = String.format(toolTipString, name, nameInternal, type1, type2); + + MapSourceLoaderInfo info = mapSource.getLoaderInfo(); + if (info != null) { + toolTipString += "
" + locLoadedFrom + ": " + info.getLoaderType().displayName; + + File f = info.getSourceFile(); + if (f != null) { + toolTipString += "
" + locFileName + ": " + StringEscapeUtils.escapeHtml4(f.getName()) + ""; + } + } + + return "" + toolTipString + ""; + } + + /** + * This method takes a list of all valid and enabled MapSources, saves them into + * internal list of MapSources, and then generates a tree model basing on them + * + * @param enabledOrderedMapSources + * - list of all MapSources that must be put into a tree. + */ + public void initialize(Vector enabledOrderedMapSources) { + mapSources = enabledOrderedMapSources; + resetTree(); + generateTreeModel(); + super.setModel(treeModel); + } + + /** + * This method will take a MapSource and will analyzed it's folder path to check + * if there is no need to put it into any folders/subfolders structure. + * + * @param mapSource + * - this mapSource's path will be analyzed + */ + private void addChildBasedOnFolderPath(MapSource mapSource) { + MapSourceLoaderInfo loaderInfo = mapSource.getLoaderInfo(); + String[] folderPath = null; + if (loaderInfo != null) { + folderPath = loaderInfo.getRelativePath(); + } + ComparableTreeNode parent = rootNode; + if (folderPath != null) { + for (String folderPathElementName : folderPath) { + + ComparableTreeNode folderPathElement = null; + ComparableTreeNode childFound = getChildByUserObject(parent, folderPathElementName); + + if (childFound != null) { + folderPathElement = childFound; + } else { + folderPathElement = new ComparableTreeNode(folderPathElementName); + insertInRightOrder(parent, folderPathElement); + } + parent = folderPathElement; + } + } + ComparableTreeNode newLeaf = new ComparableTreeNode(mapSource); + insertInRightOrder(parent, newLeaf); + } + + /** + * This method clears a tree and its model to make sure it is ready for + * (re)initialization + */ + private void resetTree() { + this.setModel(null); + rootNode.removeAllChildren(); + } + + /** + * This method inserts a node into a tree in an order based on comparator from + * ComparableTreeNode + * + * @param parentNode + * - a parent node to which a new node will be attached + * @param insertedNode + * - a new node + */ + private void insertInRightOrder(ComparableTreeNode parentNode, ComparableTreeNode insertedNode) { + int parentChildCount = treeModel.getChildCount(parentNode); + int insertIndex = 0; + + if (parentChildCount != 0) { + insertIndex = parentChildCount; + for (int i = parentChildCount - 1; i >= 0; i--) { + ComparableTreeNode child = (ComparableTreeNode) treeModel.getChild(parentNode, i); + + if (insertedNode.compareTo(child) <= 0) { + insertIndex = i; + } else { + break; + } + } + } + treeModel.insertNodeInto(insertedNode, parentNode, insertIndex); + } + + /** + * Method is iterating over all MapSources and adding them to a tree's model in + * an appropriate place + */ + private void generateTreeModel() { + for (MapSource mapSource : this.mapSources) { + addChildBasedOnFolderPath(mapSource); + } + } + + /** + * This method searches for an index of a MapSource with a requested name + * + * @param mapSourceName + * - name of a sought MapSource + * @return index of found MapSource or -1 in case nothing was found + */ + private int getMapSourceIndexByName(String mapSourceName) { + for (int i = 0; i < mapSources.size(); i++) { + MapSource mapSource = mapSources.get(i); + String mapSourceAsString = mapSource.toString(); + if (mapSourceAsString.equals(mapSourceName)) { + return i; + } + } + return -1; + } + + /** + * This method searches for a MapSource object with a requested name + * + * @param mapSourceName + * - name of a sought MapSource + * @return found MapSource object or null otherwise + */ + private MapSource getMapSourceByName(String mapSourceName) { + int mapSourceIndex = getMapSourceIndexByName(mapSourceName); + + if (mapSourceIndex == -1) { + return null; + } + return this.mapSources.get(mapSourceIndex); + } + + /** + * This method searches for a TreePath of a requested MapSouce + * + * @param mapSource + * - analyzed mapSource object + * @return TreePath of a specified MapSource or null otherwise + */ + private TreePath findTreePathOfMapSource(MapSource mapSource) { + Enumeration rootDescendants = rootNode.depthFirstEnumeration(); + while (rootDescendants.hasMoreElements()) { + ComparableTreeNode descendantNode = (ComparableTreeNode) rootDescendants.nextElement(); + + if (descendantNode.getUserObject().equals(mapSource)) { + return new TreePath(descendantNode.getPath()); + } + } + return null; + } + + /** + * This method is a main gateway for selecting a mapSource, it should be used by + * other functions. Firstly it searches for a requested MapSource and if it will + * find it, it will mark it internally as selected and then it will be passed to + * be selected in a graphical tree. + * + * @param mapSourceToSelect + * - MapSource that will be internally marked as selected + * @return a true if MapSource was found, false otherwise + */ + public boolean selectMapSource(MapSource mapSourceToSelect) { + int foundMapSourceIndex = mapSources.indexOf(mapSourceToSelect); + if (foundMapSourceIndex != -1) { + previouslySelectedMapSource = selectedMapSource; + // Marking internally as selected MapSource + selectedMapSource = mapSourceToSelect; + chooseAndShowTreeNodeInTree(mapSourceToSelect); + return true; + } + return false; + } + + /** + * This method is selecting a requested MapSource and focusing on it IN A TREE. + * MapSource is not being marked internally as selected in this method. + * + * @param mapSourceToSelect + * - MapSource that will be selected + */ + private void chooseAndShowTreeNodeInTree(MapSource mapSourceToSelect) { + TreePath pathFound = findTreePathOfMapSource(mapSourceToSelect); + if (pathFound != null) { + // Expand all folders and subfolders to show a chosen node + expandPath(pathFound.getParentPath()); + // Choose the node + setSelectionPath(pathFound); + // Scroll a JTree viewport to the chosen node + scrollPathToVisibleVerticalOnly(pathFound); + // Signaling to refresh a node, after its font/color was changed + ((DefaultTreeModel) this.getModel()).nodeChanged((TreeNode) pathFound.getLastPathComponent()); + } + } + + /** + * This method will vertically scroll to the requested treePath, but without + * touching a horizontal scroll-bar + * + * @param treePath + * - TreePath to be vertically scrolled to + */ + private void scrollPathToVisibleVerticalOnly(TreePath treePath) { + if (treePath != null) { + makeVisible(treePath); + + Rectangle pathBounds = getPathBounds(treePath); + if (pathBounds != null) { + pathBounds.x = 0; + scrollRectToVisible(pathBounds); + } + } + } + + /** + * This method should be called after clicking on any node in a tree. It gets a + * clicked/chosen node from a tree and pass it to the method that will mark it + * as internally selected. + * + * @return true if clicked MapSource was successfully selected internally, false + * otherwise + */ + public boolean selectClickedMapSource() { + if (getSelectionPath() != null) { + String selectedTreeElement = getSelectionPath().getLastPathComponent().toString(); + MapSource foundMapSource = getMapSourceByName(selectedTreeElement); + if (foundMapSource == null) { + // React if a non-MapSource node was clicked + setSelectionPath(findTreePathOfMapSource(previouslySelectedMapSource)); + } else { + // A mapSource type was clicked + return selectMapSource(foundMapSource); + } + } + return false; + } + + /** + * @return internally selected MapSource + */ + public MapSource getSelectedMapSource() { + return selectedMapSource; + } + + /** + * Selects a next MapSource from internal list of MapSources + */ + public boolean selectNextMapSource() { + if (mapSources.lastElement().equals(selectedMapSource)) { + return false; + } else { + int indexOfSelectedMapSource = mapSources.indexOf(selectedMapSource); + return selectMapSource(mapSources.get(indexOfSelectedMapSource + 1)); + } + } + + /** + * Selects a previous MapSource from internal list of MapSources + */ + public boolean selectPreviousMapSource() { + if (mapSources.firstElement().equals(selectedMapSource)) { + return false; + } else { + int indexOfSelectedMapSource = mapSources.indexOf(selectedMapSource); + return selectMapSource(mapSources.get(indexOfSelectedMapSource - 1)); + } + } + + /** + * Selects a first MapSource from internal list of MapSources. Because internal + * list is not in the same order as nodes in tree, user gets a random (from his + * point of view) MapSource. Perhaps, this method should ask user what MapSource + * he want to pick, or maybe automatically select a closest sibling of the + * previously selected MapSource? + */ + public boolean selectFirstMapSource() { + return selectMapSource(mapSources.get(0)); + } + + /** + * @return a size of internal list of MapSources + */ + public int getMapSourcesCount() { + return mapSources.size(); + } + + /** + * Check if the mouse cursor was over a clickable node + * + * @param eventPoint + * - a mouse position coordinates + * @return true if a node was clickable, false otherwise + */ + public boolean isLocationClickable(Point eventPoint) { + int x = (int) eventPoint.getX(); + int y = (int) eventPoint.getY(); + TreePath treePathForXY = getPathForLocation(x, y); + + // If a node is an ancestor of a currently selected node - it can't be closed, + // so it is unclickable. + if (treePathForXY != null && treePathForXY.isDescendant(findTreePathOfMapSource(selectedMapSource))) { + return false; + } + + boolean isInside = false; + if (treePathForXY != null) { + Rectangle pathBounds = this.getPathBounds(treePathForXY); + isInside = pathBounds.contains(eventPoint); + } + return isInside; + } + + @Override + public String getToolTipText(MouseEvent event) { + if (getRowForLocation(event.getX(), event.getY()) == -1) { + return ""; + } + TreePath curPath = getPathForLocation(event.getX(), event.getY()); + Object lastPathComponent = curPath.getLastPathComponent(); + if (lastPathComponent == null) { + return null; + } + + Object userObject = ((ComparableTreeNode) lastPathComponent).getUserObject(); + if (userObject.getClass().equals(folderClass)) { + return null; + } + return generateMapSourceTooltip((MapSource) userObject); + } + + /** + * CustomIconRenderer was created to manage icons within a tree + */ + static class CustomIconRenderer extends DefaultTreeCellRenderer { + private static final long serialVersionUID = 1L; + + private final ImageIcon multiLayerIcon; + private final ImageIcon fileBasedIcon; + private final ImageIcon httpIcon; + private final ImageIcon debugIcon; + private final ImageIcon folderOpenedIcon; + private final ImageIcon folderClosedIcon; + + public CustomIconRenderer() { + multiLayerIcon = new ImageIcon(Utilities.getResourceImageUrl("icon_multilayer_ms.png")); + fileBasedIcon = new ImageIcon(Utilities.getResourceImageUrl("icon_filebased_ms.png")); + httpIcon = new ImageIcon(Utilities.getResourceImageUrl("icon_http_ms.png")); + debugIcon = new ImageIcon(Utilities.getResourceImageUrl("icon_debug_ms.png")); + folderOpenedIcon = new ImageIcon(Utilities.getResourceImageUrl("icon_folder_opened.png")); + folderClosedIcon = new ImageIcon(Utilities.getResourceImageUrl("icon_folder_closed.png")); + } + + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, + boolean leaf, int row, boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); + + setTextSelectionColor(getTextNonSelectionColor()); + setBorderSelectionColor(null); + + if (selected) { + // Special style for selected node + this.setFont(getFont().deriveFont(Font.BOLD)); + setBackgroundSelectionColor(mapSourceInTreeHighlightColor); + } else { + this.setFont(getFont().deriveFont(Font.PLAIN)); + setBackgroundSelectionColor(null); + } + + // Adding additional left margin of icon + setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0)); + + // Setting icons for opened/closed folder + setOpenIcon(folderOpenedIcon); + setClosedIcon(folderClosedIcon); + + Object treeNodeObject = ((DefaultMutableTreeNode) value).getUserObject(); + + // Giving a appropriate icon to each category of MapSource (taken from node's + // userObject) + if (treeNodeObject instanceof AbstractMultiLayerMapSource) { + setIcon(multiLayerIcon); + } else if (treeNodeObject instanceof FileBasedMapSource) { + setIcon(fileBasedIcon); + } else if (treeNodeObject instanceof HttpMapSource) { + setIcon(httpIcon); + } else if (treeNodeObject instanceof MapSource) { + setIcon(debugIcon); + } + return this; + } + } + + /** + * ComparableTreeNode is a DefaultMutableTreeNode with a mechanism of comparison + * with other nodes. This is used when putting a node into a tree in an + * alphabetic order and placing folder nodes above other types of nodes. + */ + static class ComparableTreeNode extends DefaultMutableTreeNode implements Comparable { + private static final long serialVersionUID = 1L; + + public ComparableTreeNode(MapSource mapSource) { + super(mapSource); + } + + public ComparableTreeNode(String string) { + super(string); + } + + @Override + public int compareTo(DefaultMutableTreeNode treeNode) { + Class thisObjectClass = this.getUserObject().getClass(); + Class comparedObjectClass = treeNode.getUserObject().getClass(); + + // This rule will always put "folders" above MapSources. + if (thisObjectClass.equals(folderClass) != comparedObjectClass.equals(folderClass)) { + return thisObjectClass.equals(folderClass) ? -1 : 1; + } + + return this.toString().compareToIgnoreCase(treeNode.toString()); + } + + } +} diff --git a/src/main/java/mobac/gui/components/JMenuItem2.java b/mobac/src/main/java/mobac/gui/components/JMenuItem2.java similarity index 75% rename from src/main/java/mobac/gui/components/JMenuItem2.java rename to mobac/src/main/java/mobac/gui/components/JMenuItem2.java index 6f47032..999619c 100644 --- a/src/main/java/mobac/gui/components/JMenuItem2.java +++ b/mobac/src/main/java/mobac/gui/components/JMenuItem2.java @@ -1,29 +1,29 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; +import javax.swing.JMenuItem; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; - -import javax.swing.JMenuItem; +import java.lang.reflect.InvocationTargetException; public class JMenuItem2 extends JMenuItem implements ActionListener { - private Class actionClass; + private final Class actionClass; public JMenuItem2(String text, int mnemonic, Class actionClass) { super(text, mnemonic); @@ -40,11 +40,10 @@ public class JMenuItem2 extends JMenuItem implements ActionListener { public void actionPerformed(ActionEvent event) { ActionListener al; try { - al = actionClass.newInstance(); + al = actionClass.getConstructor().newInstance(); al.actionPerformed(event); - } catch (InstantiationException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException e) { throw new RuntimeException(e); } } diff --git a/src/main/java/mobac/gui/components/JObjectCheckBox.java b/mobac/src/main/java/mobac/gui/components/JObjectCheckBox.java similarity index 91% rename from src/main/java/mobac/gui/components/JObjectCheckBox.java rename to mobac/src/main/java/mobac/gui/components/JObjectCheckBox.java index e429aa7..00e8c57 100644 --- a/src/main/java/mobac/gui/components/JObjectCheckBox.java +++ b/mobac/src/main/java/mobac/gui/components/JObjectCheckBox.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; @@ -23,14 +23,14 @@ import javax.swing.JCheckBox; /** * An extended {@link JCheckBox} implementation that allows to link one user * object to the checkbox. - * + * * @param * type of the user object linked/stored with the checkbox */ public class JObjectCheckBox extends JCheckBox { private static final long serialVersionUID = 1L; - + private E object; public JObjectCheckBox(Icon icon) { diff --git a/src/main/java/mobac/gui/components/JProfilesComboBox.java b/mobac/src/main/java/mobac/gui/components/JProfilesComboBox.java similarity index 81% rename from src/main/java/mobac/gui/components/JProfilesComboBox.java rename to mobac/src/main/java/mobac/gui/components/JProfilesComboBox.java index f31b44f..ac64dfb 100644 --- a/src/main/java/mobac/gui/components/JProfilesComboBox.java +++ b/mobac/src/main/java/mobac/gui/components/JProfilesComboBox.java @@ -1,33 +1,33 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; +import mobac.program.model.Profile; + import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JTextField; import javax.swing.border.EmptyBorder; import javax.swing.plaf.basic.BasicComboBoxEditor; -import mobac.program.model.Profile; - /** * An editable {@link JComboBox} for displaying the saved atlases profiles. */ -public class JProfilesComboBox extends JComboBox { +public class JProfilesComboBox extends JComboBox { private static final long serialVersionUID = 1L; @@ -38,14 +38,15 @@ public class JProfilesComboBox extends JComboBox { } public void loadProfilesList() { - setModel(new DefaultComboBoxModel(Profile.getProfiles())); + setModel(new DefaultComboBoxModel(Profile.getProfiles())); setSelectedIndex(-1); } public boolean deleteSelectedProfile() { Profile profile = (Profile) getSelectedItem(); - if (profile == null) + if (profile == null) { return false; + } profile.delete(); setSelectedIndex(-1); removeItem(profile); @@ -53,16 +54,16 @@ public class JProfilesComboBox extends JComboBox { } /** - * - * @return the selected profile or null if no profile is - * selected or a new unsaved profile is selected + * @return the selected profile or null if no profile is selected + * or a new unsaved profile is selected */ public Profile getSelectedProfile() { Object selItem = getSelectedItem(); - if (selItem instanceof Profile) + if (selItem instanceof Profile) { return (Profile) selItem; - else - return null; + } + return null; + } protected static class ProfilesComboBoxEditor extends BasicComboBoxEditor { diff --git a/src/main/java/mobac/gui/components/JRegexTextField.java b/mobac/src/main/java/mobac/gui/components/JRegexTextField.java similarity index 90% rename from src/main/java/mobac/gui/components/JRegexTextField.java rename to mobac/src/main/java/mobac/gui/components/JRegexTextField.java index 6605ef0..58fbefc 100644 --- a/src/main/java/mobac/gui/components/JRegexTextField.java +++ b/mobac/src/main/java/mobac/gui/components/JRegexTextField.java @@ -1,28 +1,27 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; -import java.awt.Toolkit; -import java.util.regex.Pattern; - import javax.swing.JTextField; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.PlainDocument; +import java.awt.Toolkit; +import java.util.regex.Pattern; public class JRegexTextField extends JTextField { @@ -46,11 +45,11 @@ public class JRegexTextField extends JTextField { this.maxLength = maxLength; } - public void insertString(int offset, String str, AttributeSet attr) - throws BadLocationException { + public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException { - if (str == null) + if (str == null) { return; + } if (!pattern.matcher(str).matches()) { Toolkit.getDefaultToolkit().beep(); diff --git a/src/main/java/mobac/gui/components/JTileSizeCombo.java b/mobac/src/main/java/mobac/gui/components/JTileSizeCombo.java similarity index 71% rename from src/main/java/mobac/gui/components/JTileSizeCombo.java rename to mobac/src/main/java/mobac/gui/components/JTileSizeCombo.java index 4ea1fd9..236cc7a 100644 --- a/src/main/java/mobac/gui/components/JTileSizeCombo.java +++ b/mobac/src/main/java/mobac/gui/components/JTileSizeCombo.java @@ -1,53 +1,50 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; -import java.util.Vector; - import mobac.utilities.I18nUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Logger; +import java.util.Vector; public class JTileSizeCombo extends JIntCombo { - private static final long serialVersionUID = 1L; - public static final int MIN = 50; - public static final int MAX = 8192; - + private static final long serialVersionUID = 1L; static Vector TILE_SIZE_VALUES; static Integer DEFAULT; - static Logger log = Logger.getLogger(JTileSizeCombo.class); + private static final Logger log = LoggerFactory.getLogger(JTileSizeCombo.class); static { - DEFAULT = new Integer(256); + DEFAULT = 256; TILE_SIZE_VALUES = new Vector(); - TILE_SIZE_VALUES.addElement(new Integer(64)); - TILE_SIZE_VALUES.addElement(new Integer(128)); + TILE_SIZE_VALUES.addElement(64); + TILE_SIZE_VALUES.addElement(128); TILE_SIZE_VALUES.addElement(DEFAULT); - TILE_SIZE_VALUES.addElement(new Integer(512)); - TILE_SIZE_VALUES.addElement(new Integer(768)); - TILE_SIZE_VALUES.addElement(new Integer(1024)); - TILE_SIZE_VALUES.addElement(new Integer(1536)); + TILE_SIZE_VALUES.addElement(512); + TILE_SIZE_VALUES.addElement(768); + TILE_SIZE_VALUES.addElement(1024); + TILE_SIZE_VALUES.addElement(1536); for (int i = 2048; i <= MAX; i += 1024) { - TILE_SIZE_VALUES.addElement(new Integer(i)); + TILE_SIZE_VALUES.addElement(i); } } diff --git a/src/main/java/mobac/gui/components/JTimeSlider.java b/mobac/src/main/java/mobac/gui/components/JTimeSlider.java similarity index 81% rename from src/main/java/mobac/gui/components/JTimeSlider.java rename to mobac/src/main/java/mobac/gui/components/JTimeSlider.java index 8fddcac..8bda83a 100644 --- a/src/main/java/mobac/gui/components/JTimeSlider.java +++ b/mobac/src/main/java/mobac/gui/components/JTimeSlider.java @@ -1,26 +1,25 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; -import java.util.Hashtable; -import java.util.concurrent.TimeUnit; - import javax.swing.JLabel; import javax.swing.JSlider; +import java.util.Hashtable; +import java.util.concurrent.TimeUnit; public class JTimeSlider extends JSlider { @@ -42,12 +41,12 @@ public class JTimeSlider extends JSlider { int day = timeToSliderValue(TimeUnit.DAYS.toMillis(1)); int month = timeToSliderValue(TimeUnit.DAYS.toMillis(31)); int year = timeToSliderValue(TimeUnit.DAYS.toMillis(365)); - LABEL_TABLE.put(new Integer(MIN), new JLabel("0 sec")); - LABEL_TABLE.put(new Integer(hour), new JLabel("1 hour")); - LABEL_TABLE.put(new Integer(day), new JLabel("1 day")); - LABEL_TABLE.put(new Integer(month), new JLabel("1 month")); - LABEL_TABLE.put(new Integer(year), new JLabel("1 year")); - LABEL_TABLE.put(new Integer(MAX), new JLabel("never")); + LABEL_TABLE.put(MIN, new JLabel("0 sec")); + LABEL_TABLE.put(hour, new JLabel("1 hour")); + LABEL_TABLE.put(day, new JLabel("1 day")); + LABEL_TABLE.put(month, new JLabel("1 month")); + LABEL_TABLE.put(year, new JLabel("1 year")); + LABEL_TABLE.put(MAX, new JLabel("never")); } public JTimeSlider() { @@ -58,6 +57,15 @@ public class JTimeSlider extends JSlider { setPaintLabels(true); } + private static long sliderToTimeValue(int sliderValue) { + return -1024000 + (long) (1000 * Math.pow(2d, sliderValue / 1000d)); + } + + private static int timeToSliderValue(long timeValue) { + + return (int) (C1 * (C2 - Math.log((timeValue + 1024000) / 125d))); + } + public long getTimeSecondsValue() { return sliderToTimeValue(super.getValue()) / 1000; } @@ -69,13 +77,4 @@ public class JTimeSlider extends JSlider { public void setTimeMilliValue(long time) { super.setValue(timeToSliderValue(time)); } - - private static long sliderToTimeValue(int sliderValue) { - return -1024000 + (long) (1000 * Math.pow(2d, sliderValue / 1000d)); - } - - private static int timeToSliderValue(long timeValue) { - - return (int) (C1 * (C2 - Math.log((timeValue + 1024000) / 125d))); - } } diff --git a/src/main/java/mobac/gui/components/JZoomCheckBox.java b/mobac/src/main/java/mobac/gui/components/JZoomCheckBox.java similarity index 87% rename from src/main/java/mobac/gui/components/JZoomCheckBox.java rename to mobac/src/main/java/mobac/gui/components/JZoomCheckBox.java index ac6883a..1e4c176 100644 --- a/src/main/java/mobac/gui/components/JZoomCheckBox.java +++ b/mobac/src/main/java/mobac/gui/components/JZoomCheckBox.java @@ -1,40 +1,39 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.components; -import javax.swing.JCheckBox; - import mobac.utilities.I18nUtils; +import javax.swing.JCheckBox; + public class JZoomCheckBox extends JCheckBox { private static final long serialVersionUID = 1L; - + private final int zoomLevel; public JZoomCheckBox(int zoomLevel) { super(); this.zoomLevel = zoomLevel; - setToolTipText(String.format(I18nUtils.localizedStringForKey("lp_zoom_number_tips"),zoomLevel)); + setToolTipText(String.format(I18nUtils.localizedStringForKey("lp_zoom_number_tips"), zoomLevel)); } public int getZoomLevel() { return zoomLevel; } - } diff --git a/src/main/java/mobac/gui/dialogs/AboutDialog.java b/mobac/src/main/java/mobac/gui/dialogs/AboutDialog.java similarity index 94% rename from src/main/java/mobac/gui/dialogs/AboutDialog.java rename to mobac/src/main/java/mobac/gui/dialogs/AboutDialog.java index bc6a59f..6405ac6 100644 --- a/src/main/java/mobac/gui/dialogs/AboutDialog.java +++ b/mobac/src/main/java/mobac/gui/dialogs/AboutDialog.java @@ -1,21 +1,32 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.dialogs; +import mobac.gui.MainGUI; +import mobac.program.ProgramInfo; +import mobac.utilities.GBC; +import mobac.utilities.I18nUtils; +import mobac.utilities.Utilities; + +import javax.swing.ImageIcon; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.UIManager; import java.awt.Color; import java.awt.Dimension; import java.awt.GridBagLayout; @@ -24,18 +35,6 @@ import java.awt.Toolkit; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; -import javax.swing.ImageIcon; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.UIManager; - -import mobac.gui.MainGUI; -import mobac.program.ProgramInfo; -import mobac.utilities.GBC; -import mobac.utilities.I18nUtils; -import mobac.utilities.Utilities; - public class AboutDialog extends JDialog implements MouseListener { public AboutDialog() throws HeadlessException { @@ -80,6 +79,17 @@ public class AboutDialog extends JDialog implements MouseListener { addMouseListener(this); } + public static void main(String[] args) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + ProgramInfo.initialize(); // Load revision info + JDialog dlg = new AboutDialog(); + dlg.setVisible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + public void mouseClicked(MouseEvent e) { setVisible(false); } @@ -95,15 +105,4 @@ public class AboutDialog extends JDialog implements MouseListener { public void mouseExited(MouseEvent e) { } - - public static void main(String[] args) { - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - ProgramInfo.initialize(); // Load revision info - JDialog dlg = new AboutDialog(); - dlg.setVisible(true); - } catch (Exception e) { - e.printStackTrace(); - } - } } diff --git a/src/main/java/mobac/gui/dialogs/FontChooser.java b/mobac/src/main/java/mobac/gui/dialogs/FontChooser.java similarity index 80% rename from src/main/java/mobac/gui/dialogs/FontChooser.java rename to mobac/src/main/java/mobac/gui/dialogs/FontChooser.java index 0eaf865..16317c3 100644 --- a/src/main/java/mobac/gui/dialogs/FontChooser.java +++ b/mobac/src/main/java/mobac/gui/dialogs/FontChooser.java @@ -1,27 +1,23 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.dialogs; -import java.awt.Dialog.ModalityType; -import java.awt.Font; -import java.awt.GraphicsEnvironment; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import mobac.utilities.GBCTable; +import mobac.utilities.I18nUtils; import javax.swing.BorderFactory; import javax.swing.JButton; @@ -33,59 +29,23 @@ import javax.swing.JScrollPane; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; - -import mobac.utilities.GBCTable; -import mobac.utilities.I18nUtils; +import java.awt.Dialog.ModalityType; +import java.awt.Font; +import java.awt.GraphicsEnvironment; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; public class FontChooser { - private static final String FONT_NAMES[] = GraphicsEnvironment.getLocalGraphicsEnvironment() - .getAvailableFontFamilyNames(); - private static final String STYLES[] = new String[] { "Plain", "Bold", "Italic", "Bold + Italic" }; - public static final Font DEFAULT = new Font(Font.SANS_SERIF, Font.PLAIN, 12); - - public static String encodeFont(Font font) { - String style; - switch (font.getStyle()) { - case Font.PLAIN: - style = "PLAIN"; - break; - case Font.BOLD: - style = "BOLD"; - break; - case Font.ITALIC: - style = "ITALIC"; - break; - case Font.BOLD | Font.ITALIC: - style = "BOLDITALIC"; - break; - default: - style = "PLAIN"; - } - return font.getName() + "-" + style + "-" + font.getSize(); - } - - private static JScrollPane scroll(JList jList, String title) { - JLabel jLabel = new JLabel(title); - jLabel.setHorizontalAlignment(JLabel.CENTER); - JScrollPane jScrollPane = new JScrollPane(jList); - jScrollPane.setColumnHeaderView(jLabel); - return jScrollPane; - } - + private static final String[] FONT_NAMES = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getAvailableFontFamilyNames(); + private static final String[] STYLES = new String[]{"Plain", "Bold", "Italic", "Bold + Italic"}; private final JDialog jDialog = new JDialog(); - private final JLabel jLabelPreview = new JLabel("DUMMY"); - - private final JList jListName = createJList(FONT_NAMES); - private final JList jListStyle = createJList(STYLES); - private final JList jListSize = createJList(new Integer[] { 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 23, 24 }); - - private final JButton jButtonOK = new JButton(I18nUtils.localizedStringForKey("OK")), jButtonCancel = new JButton( - I18nUtils.localizedStringForKey("Cancel")); - + private final JButton jButtonOK = new JButton(I18nUtils.localizedStringForKey("OK")), + jButtonCancel = new JButton(I18nUtils.localizedStringForKey("Cancel")); private boolean wasCanceled; public FontChooser() { @@ -94,8 +54,8 @@ public class FontChooser { jLabelPreview.setHorizontalAlignment(JLabel.CENTER); jLabelPreview.setVerticalAlignment(JLabel.CENTER); - jLabelPreview.setBorder(BorderFactory.createTitledBorder(I18nUtils - .localizedStringForKey("dlg_font_choose_preview"))); + jLabelPreview.setBorder( + BorderFactory.createTitledBorder(I18nUtils.localizedStringForKey("dlg_font_choose_preview"))); jButtonOK.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -130,6 +90,33 @@ public class FontChooser { setFont(DEFAULT); } + public static String encodeFont(Font font) { + String style; + switch (font.getStyle()) { + case Font.BOLD : + style = "BOLD"; + break; + case Font.ITALIC : + style = "ITALIC"; + break; + case Font.BOLD | Font.ITALIC : + style = "BOLDITALIC"; + break; + default : + style = "PLAIN"; + } + return font.getName() + "-" + style + "-" + font.getSize(); + } + + private static JScrollPane scroll(JList jList, String title) { + JLabel jLabel = new JLabel(title); + jLabel.setHorizontalAlignment(JLabel.CENTER); + JScrollPane jScrollPane = new JScrollPane(jList); + jScrollPane.setColumnHeaderView(jLabel); + return jScrollPane; + } + private final JList jListName = createJList(FONT_NAMES); + private JList createJList(E[] objects) { JList jList = new JList(objects); jList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); @@ -145,6 +132,22 @@ public class FontChooser { return jList; } + public Font getFont() { + String name = jListName.getSelectedValue(); + if (name == null) { + name = DEFAULT.getName(); + } + int style = jListStyle.getSelectedIndex(); + if (style == -1) { + style = DEFAULT.getStyle(); + } + Integer size = jListSize.getSelectedValue(); + if (size == null) { + size = DEFAULT.getSize(); + } + return new Font(name, style, size); + } + public void setFont(Font font) { if (font == null) { font = DEFAULT; @@ -153,22 +156,7 @@ public class FontChooser { jListStyle.setSelectedIndex(font.getStyle()); jListSize.setSelectedValue(font.getSize(), true); } - - public Font getFont() { - String name = (String) jListName.getSelectedValue(); - if (name == null) { - name = DEFAULT.getName(); - } - int style = jListStyle.getSelectedIndex(); - if (style == -1) { - style = DEFAULT.getStyle(); - } - Integer size = (Integer) jListSize.getSelectedValue(); - if (size == null) { - size = DEFAULT.getSize(); - } - return new Font(name, style, size); - } + private final JList jListStyle = createJList(STYLES); public void show() { wasCanceled = true; @@ -179,4 +167,8 @@ public class FontChooser { public boolean wasCanceled() { return wasCanceled; } + + private final JList jListSize = createJList( + new Integer[]{8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}); + } diff --git a/src/main/java/mobac/gui/dialogs/Help.java b/mobac/src/main/java/mobac/gui/dialogs/Help.java similarity index 83% rename from src/main/java/mobac/gui/dialogs/Help.java rename to mobac/src/main/java/mobac/gui/dialogs/Help.java index b8e8edb..62d4b74 100644 --- a/src/main/java/mobac/gui/dialogs/Help.java +++ b/mobac/src/main/java/mobac/gui/dialogs/Help.java @@ -1,21 +1,28 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.dialogs; +import mobac.gui.MainGUI; +import mobac.utilities.GBC; +import mobac.utilities.I18nUtils; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; import java.awt.Dimension; import java.awt.GridBagLayout; import java.awt.HeadlessException; @@ -24,28 +31,14 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; -import java.io.DataInputStream; import java.io.IOException; - -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; - -import mobac.gui.MainGUI; -import mobac.utilities.Charsets; -import mobac.utilities.GBC; -import mobac.utilities.I18nUtils; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; public class Help extends JFrame implements WindowListener { private static Help INSTANCE = null; - public static synchronized void showHelp() { - if (INSTANCE == null) - INSTANCE = new Help(); - INSTANCE.setVisible(true); - } - public Help() throws HeadlessException { super(I18nUtils.localizedStringForKey("dlg_help_title")); setIconImages(MainGUI.MOBAC_ICONS); @@ -61,14 +54,9 @@ public class Help extends JFrame implements WindowListener { } }); - DataInputStream in = new DataInputStream( - I18nUtils.getI18nResourceAsStream("resources/text/help_dialog", "html")); - byte[] buf; - try { - buf = new byte[in.available()]; - in.readFully(buf); - in.close(); - String helpMessage = new String(buf, Charsets.UTF_8); + try (InputStream in = I18nUtils.getI18nResourceAsStream("resources/text/help_dialog", "html")) { + byte[] buf = in.readAllBytes(); + String helpMessage = new String(buf, StandardCharsets.UTF_8); // Strip out all line breaks because JOptionPane shows // the raw HTML code otherwise // helpMessage = helpMessage.replaceAll("\n", ""); @@ -87,6 +75,13 @@ public class Help extends JFrame implements WindowListener { setResizable(false); } + public static synchronized void showHelp() { + if (INSTANCE == null) { + INSTANCE = new Help(); + } + INSTANCE.setVisible(true); + } + public void windowActivated(WindowEvent e) { } diff --git a/src/main/java/mobac/gui/dialogs/LicensesDialog.java b/mobac/src/main/java/mobac/gui/dialogs/LicensesDialog.java similarity index 83% rename from src/main/java/mobac/gui/dialogs/LicensesDialog.java rename to mobac/src/main/java/mobac/gui/dialogs/LicensesDialog.java index 1b9f750..e177233 100644 --- a/src/main/java/mobac/gui/dialogs/LicensesDialog.java +++ b/mobac/src/main/java/mobac/gui/dialogs/LicensesDialog.java @@ -1,28 +1,26 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.dialogs; -import java.awt.Dimension; -import java.awt.GridBagLayout; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.image.BufferedImage; -import java.io.IOException; +import mobac.gui.MainGUI; +import mobac.program.ProgramInfo; +import mobac.utilities.GBC; +import mobac.utilities.I18nUtils; +import mobac.utilities.Utilities; import javax.swing.Icon; import javax.swing.ImageIcon; @@ -35,26 +33,32 @@ import javax.swing.JTextArea; import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; - -import mobac.gui.MainGUI; -import mobac.program.ProgramInfo; -import mobac.utilities.GBC; -import mobac.utilities.I18nUtils; -import mobac.utilities.Utilities; +import java.awt.Dimension; +import java.awt.GridBagLayout; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.image.BufferedImage; +import java.io.IOException; public class LicensesDialog extends JFrame implements ChangeListener, ActionListener { - private LicenseInfo[] licenses = new LicenseInfo[] { new LicenseInfo("

Mobile Atlas Creator

", "gpl.txt"), - new LicenseInfo("

Library Apache Log4J

", "apache-2.0.txt"), + private final JTextArea textArea; + private final JTabbedPane tab; + private final LicenseInfo[] licenses = new LicenseInfo[]{ // + new LicenseInfo("

Mobile Atlas Creator

", "gpl.txt"), + new LicenseInfo("

Library slf4j

", "mit.txt"), + new LicenseInfo("

Library Logback

", "lgpl-2.1.txt"), new LicenseInfo("

Library Apache Commons Codec

", "apache-2.0.txt"), new LicenseInfo("

Library Apache Commons IO

", "apache-2.0.txt"), + new LicenseInfo("

Library Apache Commons Text

", "apache-2.0.txt"), new LicenseInfo("

Library Berkely-DB JavaEdition

", "license-dbd-je.txt"), new LicenseInfo("

Library BeanShell

", "lgpl-3.0.txt"), new LicenseInfo("

Library JavaPNG

", "gpl.txt"), - new LicenseInfo("

Library iTextPDF

", "agpl.txt") }; - - private final JTextArea textArea; - private final JTabbedPane tab; + new LicenseInfo("

Library iTextPDF

", "agpl.txt"), + new LicenseInfo("

Library sqlite-jdbc

", "apache-2.0.txt"), + new LicenseInfo("

mapsforge

", "lgpl-3.0.txt"), + new LicenseInfo("

Silk Icons

", "cc-attribution-2.5.txt")}; private String currentLicense = null; public LicensesDialog() { @@ -90,12 +94,24 @@ public class LicensesDialog extends JFrame implements ChangeListener, ActionList setLocation((dim.width - getWidth()) / 2, (dim.height - getHeight()) / 2); } + public static void main(String[] args) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + ProgramInfo.initialize(); // Load revision info + JFrame dlg = new LicensesDialog(); + dlg.setVisible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + public void stateChanged(ChangeEvent event) { String license; try { String nextLicense = licenses[tab.getSelectedIndex()].licenseResource; - if (nextLicense.equals(currentLicense)) + if (nextLicense.equals(currentLicense)) { return; + } license = Utilities.loadTextResource("text/" + nextLicense); currentLicense = nextLicense; } catch (IOException e) { @@ -121,15 +137,4 @@ public class LicensesDialog extends JFrame implements ChangeListener, ActionList } } - - public static void main(String[] args) { - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - ProgramInfo.initialize(); // Load revision info - JFrame dlg = new LicensesDialog(); - dlg.setVisible(true); - } catch (Exception e) { - e.printStackTrace(); - } - } } diff --git a/src/main/java/mobac/gui/dialogs/ManageBookmarks.java b/mobac/src/main/java/mobac/gui/dialogs/ManageBookmarks.java similarity index 80% rename from src/main/java/mobac/gui/dialogs/ManageBookmarks.java rename to mobac/src/main/java/mobac/gui/dialogs/ManageBookmarks.java index f1bd36c..db4db05 100644 --- a/src/main/java/mobac/gui/dialogs/ManageBookmarks.java +++ b/mobac/src/main/java/mobac/gui/dialogs/ManageBookmarks.java @@ -1,21 +1,34 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.dialogs; +import mobac.gui.MainGUI; +import mobac.program.model.Bookmark; +import mobac.program.model.Settings; +import mobac.utilities.GBC; +import mobac.utilities.I18nUtils; + +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JList; +import javax.swing.ListSelectionModel; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; import java.awt.Dimension; import java.awt.GridBagLayout; import java.awt.HeadlessException; @@ -25,33 +38,15 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; -import javax.swing.DefaultListModel; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JList; -import javax.swing.ListSelectionModel; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; -import javax.xml.bind.JAXBException; - -import mobac.gui.MainGUI; -import mobac.program.DirectoryManager; -import mobac.program.Logging; -import mobac.program.model.Bookmark; -import mobac.program.model.Settings; -import mobac.utilities.GBC; -import mobac.utilities.GUIExceptionHandler; -import mobac.utilities.I18nUtils; - public class ManageBookmarks extends JDialog implements ListSelectionListener, ActionListener { - private JButton deleteButton; + private final JButton deleteButton; - private JButton applyButton; + private final JButton applyButton; - private JList bookmarks; + private final JList bookmarks; - private DefaultListModel bookmarksModel; + private final DefaultListModel bookmarksModel; public ManageBookmarks(Window owner) throws HeadlessException { super(owner, I18nUtils.localizedStringForKey("dlg_mgn_bookmark_title")); @@ -65,8 +60,9 @@ public class ManageBookmarks extends JDialog implements ListSelectionListener, A deleteButton.addActionListener(this); bookmarksModel = new DefaultListModel(); - for (Bookmark b : Settings.getInstance().placeBookmarks) + for (Bookmark b : Settings.getInstance().placeBookmarks) { bookmarksModel.addElement(b); + } bookmarks = new JList(bookmarksModel); bookmarks.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); bookmarks.addListSelectionListener(this); @@ -85,22 +81,25 @@ public class ManageBookmarks extends JDialog implements ListSelectionListener, A } public void actionPerformed(ActionEvent e) { - if (deleteButton.equals(e.getSource())) + if (deleteButton.equals(e.getSource())) { deleteSelectedEntries(); - else if (applyButton.equals(e.getSource())) + } else if (applyButton.equals(e.getSource())) { apply(); + } } protected void deleteSelectedEntries() { int[] selected = bookmarks.getSelectedIndices(); - for (int i = selected.length - 1; i >= 0; i--) + for (int i = selected.length - 1; i >= 0; i--) { bookmarksModel.remove(selected[i]); + } } protected void apply() { ArrayList bookmarksList = new ArrayList(bookmarksModel.getSize()); - for (int i = 0; i < bookmarksModel.getSize(); i++) - bookmarksList.add((Bookmark) bookmarksModel.get(i)); + for (int i = 0; i < bookmarksModel.getSize(); i++) { + bookmarksList.add(bookmarksModel.get(i)); + } Settings.getInstance().placeBookmarks = bookmarksList; setVisible(false); dispose(); diff --git a/src/main/java/mobac/gui/dialogs/MessageDialogs.java b/mobac/src/main/java/mobac/gui/dialogs/MessageDialogs.java similarity index 90% rename from src/main/java/mobac/gui/dialogs/MessageDialogs.java rename to mobac/src/main/java/mobac/gui/dialogs/MessageDialogs.java index ab4dafb..92fcb4d 100644 --- a/src/main/java/mobac/gui/dialogs/MessageDialogs.java +++ b/mobac/src/main/java/mobac/gui/dialogs/MessageDialogs.java @@ -1,32 +1,31 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.dialogs; -import java.awt.Component; -import java.awt.Dimension; +import mobac.utilities.I18nUtils; import javax.swing.JLabel; import javax.swing.JOptionPane; - -import mobac.utilities.I18nUtils; +import java.awt.Component; +import java.awt.Dimension; public class MessageDialogs { - public static void showErrorMessage(Component parentComponent, String message, String title) { + public static void showErrorMessage(Component parentComponent, String message) { JLabel label = new JLabel("" + message + ""); int maxWidth = 400; Dimension size = label.getPreferredSize(); diff --git a/src/main/java/mobac/gui/dialogs/WorkinprogressDialog.java b/mobac/src/main/java/mobac/gui/dialogs/WorkinprogressDialog.java similarity index 87% rename from src/main/java/mobac/gui/dialogs/WorkinprogressDialog.java rename to mobac/src/main/java/mobac/gui/dialogs/WorkinprogressDialog.java index dc2d11e..e070a16 100644 --- a/src/main/java/mobac/gui/dialogs/WorkinprogressDialog.java +++ b/mobac/src/main/java/mobac/gui/dialogs/WorkinprogressDialog.java @@ -1,21 +1,32 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.dialogs; +import mobac.program.tilestore.berkeleydb.DelayedInterruptThread; +import mobac.utilities.I18nUtils; +import mobac.utilities.Utilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.Frame; @@ -26,21 +37,9 @@ import java.awt.event.WindowListener; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JDialog; -import javax.swing.JFrame; -import javax.swing.JLabel; - -import mobac.program.tilestore.berkeleydb.DelayedInterruptThread; -import mobac.utilities.I18nUtils; -import mobac.utilities.Utilities; - -import org.apache.log4j.Logger; - public class WorkinprogressDialog extends JDialog implements WindowListener { - private static final Logger log = Logger.getLogger(WorkinprogressDialog.class); + private static final Logger log = LoggerFactory.getLogger(WorkinprogressDialog.class); private final ThreadFactory threadFactory; private Thread workerThread; @@ -57,7 +56,7 @@ public class WorkinprogressDialog extends JDialog implements WindowListener { setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); setLocationRelativeTo(owner); addWindowListener(this); - JButton abort = new JButton(I18nUtils.localizedStringForKey("dlg_progress_about_btn")); + JButton abort = new JButton(I18nUtils.localizedStringForKey("Abort")); abort.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -69,6 +68,44 @@ public class WorkinprogressDialog extends JDialog implements WindowListener { pack(); } + public static void main(String[] args) { + JFrame parentFrame = new JFrame(); + parentFrame.setSize(500, 150); + final JLabel jl = new JLabel(); + jl.setText(I18nUtils.localizedStringForKey("dlg_progress_count")); + + parentFrame.add(BorderLayout.CENTER, jl); + parentFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + parentFrame.setVisible(true); + + final WorkinprogressDialog dlg = new WorkinprogressDialog(parentFrame, + I18nUtils.localizedStringForKey("dlg_progress_title"), DelayedInterruptThread.createThreadFactory()); + + final Thread t = new Thread() { + + @Override + public void run() { + try { + for (int i = 0; i <= 500; i++) { + jl.setText(String.format(I18nUtils.localizedStringForKey("dlg_progress_count_i"), i)); + if (Thread.currentThread().isInterrupted()) { + System.out.println("Aborted"); + return; + } + Thread.sleep(25); + } + } catch (InterruptedException e) { + System.out.println("Aborted"); + } finally { + dlg.setVisible(false); + } + } + + }; + dlg.startWork(t); + } + public void startWork(final Runnable r) { workerThread = threadFactory.newThread(new Runnable() { @@ -132,43 +169,4 @@ public class WorkinprogressDialog extends JDialog implements WindowListener { public void windowIconified(WindowEvent event) { } - - public static void main(String[] args) { - JFrame parentFrame = new JFrame(); - parentFrame.setSize(500, 150); - final JLabel jl = new JLabel(); - jl.setText(I18nUtils.localizedStringForKey("dlg_progress_count")); - - parentFrame.add(BorderLayout.CENTER, jl); - parentFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - parentFrame.setVisible(true); - - final WorkinprogressDialog dlg = new WorkinprogressDialog(parentFrame, I18nUtils.localizedStringForKey("dlg_progress_title"), - DelayedInterruptThread.createThreadFactory()); - - final Thread t = new Thread() { - - @Override - public void run() { - try { - for (int i = 0; i <= 500; i++) { - jl.setText(String.format(I18nUtils.localizedStringForKey("dlg_progress_count_i"),i)); - if (Thread.currentThread().isInterrupted()) { - System.out.println("Aborted"); - return; - } - Thread.sleep(25); - } - } catch (InterruptedException e) { - System.out.println("Aborted"); - return; - } finally { - dlg.setVisible(false); - } - } - - }; - dlg.startWork(t); - } } diff --git a/src/main/java/mobac/gui/gpxtree/GpxEntry.java b/mobac/src/main/java/mobac/gui/gpxtree/GpxEntry.java similarity index 80% rename from src/main/java/mobac/gui/gpxtree/GpxEntry.java rename to mobac/src/main/java/mobac/gui/gpxtree/GpxEntry.java index 9ddb77b..3d1c076 100644 --- a/src/main/java/mobac/gui/gpxtree/GpxEntry.java +++ b/mobac/src/main/java/mobac/gui/gpxtree/GpxEntry.java @@ -1,65 +1,67 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.gpxtree; -import javax.swing.tree.DefaultMutableTreeNode; - import mobac.gui.mapview.layer.GpxLayer; +import javax.swing.tree.DefaultMutableTreeNode; + /** - * Generalized entry in the gpx tree. All actual entries derive from this class. The class encapsulates everything - * gui-related as well as the actual gpx data for the editor. Subclasses: {@link GpxRootEntry}, {@link TrkEntry}, + * Generalized entry in the gpx tree. All actual entries derive from this class. + * The class encapsulates everything gui-related as well as the actual gpx data + * for the editor. Subclasses: {@link GpxRootEntry}, {@link TrkEntry}, * {@link RteEntry}, {@link WptEntry} - * + * * @author lhoeppner - * */ public class GpxEntry { private DefaultMutableTreeNode node; private GpxLayer layer; - /** determines whether an entry can be a parent for waypoints */ + /** + * determines whether an entry can be a parent for waypoints + */ private boolean isWaypointParent = false; - public void setLayer(GpxLayer layer) { - this.layer = layer; - } - public GpxLayer getLayer() { return layer; } - /** - * Remembers the associated tree node. - * - * @param node - */ - public void setNode(DefaultMutableTreeNode node) { - this.node = node; + public void setLayer(GpxLayer layer) { + this.layer = layer; } public DefaultMutableTreeNode getNode() { return node; } - public void setWaypointParent(boolean isWaypointParent) { - this.isWaypointParent = isWaypointParent; + /** + * Remembers the associated tree node. + * + * @param node + */ + public void setNode(DefaultMutableTreeNode node) { + this.node = node; } public boolean isWaypointParent() { return isWaypointParent; } + + public void setWaypointParent(boolean isWaypointParent) { + this.isWaypointParent = isWaypointParent; + } } diff --git a/src/main/java/mobac/gui/gpxtree/GpxRootEntry.java b/mobac/src/main/java/mobac/gui/gpxtree/GpxRootEntry.java similarity index 87% rename from src/main/java/mobac/gui/gpxtree/GpxRootEntry.java rename to mobac/src/main/java/mobac/gui/gpxtree/GpxRootEntry.java index 269c081..dc06fc7 100644 --- a/src/main/java/mobac/gui/gpxtree/GpxRootEntry.java +++ b/mobac/src/main/java/mobac/gui/gpxtree/GpxRootEntry.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.gpxtree; @@ -36,8 +36,8 @@ public class GpxRootEntry extends GpxEntry { if (getLayer().getFile() == null) { return I18nUtils.localizedStringForKey("rp_gpx_root_default_name_nofile"); } else { - return String.format(I18nUtils.localizedStringForKey("rp_gpx_root_default_name_hasfile"), getLayer() - .getFile().getName()); + return String.format(I18nUtils.localizedStringForKey("rp_gpx_root_default_name_hasfile"), + getLayer().getFile().getName()); } } } @@ -52,8 +52,9 @@ public class GpxRootEntry extends GpxEntry { public void setMetaDataName(String name) { Gpx gpx = getLayer().getGpx(); - if (gpx.getMetadata() == null) + if (gpx.getMetadata() == null) { gpx.setMetadata(new MetadataType()); + } gpx.getMetadata().setName(name); // Notify the model about the changed node text diff --git a/src/main/java/mobac/gui/gpxtree/GpxTreeListener.java b/mobac/src/main/java/mobac/gui/gpxtree/GpxTreeListener.java similarity index 89% rename from src/main/java/mobac/gui/gpxtree/GpxTreeListener.java rename to mobac/src/main/java/mobac/gui/gpxtree/GpxTreeListener.java index 3900c31..d5fe0bf 100644 --- a/src/main/java/mobac/gui/gpxtree/GpxTreeListener.java +++ b/mobac/src/main/java/mobac/gui/gpxtree/GpxTreeListener.java @@ -1,43 +1,40 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.gpxtree; -import java.awt.Component; -import java.awt.event.ActionEvent; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; +import mobac.gui.actions.GpxElementListener; +import mobac.utilities.I18nUtils; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JTree; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; - -import mobac.gui.actions.GpxElementListener; -import mobac.utilities.I18nUtils; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; /** * Listener for the gpx editor tree. - * + * * @author lhoeppner - * */ public class GpxTreeListener implements MouseListener { - private JPopupMenu popup; public void actionPerformed(ActionEvent e) { } @@ -64,16 +61,18 @@ public class GpxTreeListener implements MouseListener { } /** - * Popup for all elements in the gpx tree. TODO separate for waypoints, files, tracks and routes - * + * Popup for all elements in the gpx tree. TODO separate for waypoints, files, + * tracks and routes + * * @param e */ private void showPopup(MouseEvent e) { JTree tree = (JTree) e.getSource(); TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); tree.setSelectionPath(selPath); - if (selPath == null) + if (selPath == null) { return; + } DefaultMutableTreeNode node = (DefaultMutableTreeNode) selPath.getLastPathComponent(); @@ -84,7 +83,7 @@ public class GpxTreeListener implements MouseListener { } catch (ClassCastException exc) { } - popup = new JPopupMenu(); + JPopupMenu popup = new JPopupMenu(); JMenuItem delete = new JMenuItem(I18nUtils.localizedStringForKey("rp_gpx_pop_menu_delete_element")); delete.setName(GpxElementListener.MENU_NAME_DELETE); GpxElementListener listener = new GpxElementListener(gpxEntry); diff --git a/src/main/java/mobac/gui/gpxtree/RteEntry.java b/mobac/src/main/java/mobac/gui/gpxtree/RteEntry.java similarity index 91% rename from src/main/java/mobac/gui/gpxtree/RteEntry.java rename to mobac/src/main/java/mobac/gui/gpxtree/RteEntry.java index 091b1b0..0d3643b 100644 --- a/src/main/java/mobac/gui/gpxtree/RteEntry.java +++ b/mobac/src/main/java/mobac/gui/gpxtree/RteEntry.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.gpxtree; @@ -43,11 +43,11 @@ public class RteEntry extends GpxEntry { } } - private void setRte(RteType rte) { - this.rte = rte; - } - public RteType getRte() { return rte; } + + private void setRte(RteType rte) { + this.rte = rte; + } } diff --git a/src/main/java/mobac/gui/gpxtree/TrkEntry.java b/mobac/src/main/java/mobac/gui/gpxtree/TrkEntry.java similarity index 91% rename from src/main/java/mobac/gui/gpxtree/TrkEntry.java rename to mobac/src/main/java/mobac/gui/gpxtree/TrkEntry.java index a9ee994..9d00e13 100644 --- a/src/main/java/mobac/gui/gpxtree/TrkEntry.java +++ b/mobac/src/main/java/mobac/gui/gpxtree/TrkEntry.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.gpxtree; diff --git a/src/main/java/mobac/gui/gpxtree/TrksegEntry.java b/mobac/src/main/java/mobac/gui/gpxtree/TrksegEntry.java similarity index 91% rename from src/main/java/mobac/gui/gpxtree/TrksegEntry.java rename to mobac/src/main/java/mobac/gui/gpxtree/TrksegEntry.java index 78441ca..fb066db 100644 --- a/src/main/java/mobac/gui/gpxtree/TrksegEntry.java +++ b/mobac/src/main/java/mobac/gui/gpxtree/TrksegEntry.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.gpxtree; diff --git a/src/main/java/mobac/gui/gpxtree/WptEntry.java b/mobac/src/main/java/mobac/gui/gpxtree/WptEntry.java similarity index 91% rename from src/main/java/mobac/gui/gpxtree/WptEntry.java rename to mobac/src/main/java/mobac/gui/gpxtree/WptEntry.java index 42c0e27..b1aacca 100644 --- a/src/main/java/mobac/gui/gpxtree/WptEntry.java +++ b/mobac/src/main/java/mobac/gui/gpxtree/WptEntry.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.gpxtree; diff --git a/src/main/java/mobac/gui/listeners/AtlasModelListener.java b/mobac/src/main/java/mobac/gui/listeners/AtlasModelListener.java similarity index 79% rename from src/main/java/mobac/gui/listeners/AtlasModelListener.java rename to mobac/src/main/java/mobac/gui/listeners/AtlasModelListener.java index 1b3bcb4..befdc4e 100644 --- a/src/main/java/mobac/gui/listeners/AtlasModelListener.java +++ b/mobac/src/main/java/mobac/gui/listeners/AtlasModelListener.java @@ -1,34 +1,34 @@ -/******************************************************************************* +/** * Copyright (c) MOBAC developers - * + *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + *

* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + *

* You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ******************************************************************************/ + * along with this program. If not, see . + */ /** - * + * */ package mobac.gui.listeners; -import javax.swing.event.TreeModelEvent; -import javax.swing.event.TreeModelListener; - import mobac.gui.atlastree.JAtlasTree; import mobac.gui.panels.JProfilesPanel; +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; + public class AtlasModelListener implements TreeModelListener { - JAtlasTree atlasTree; - JProfilesPanel profilesPanel; + final JAtlasTree atlasTree; + final JProfilesPanel profilesPanel; public AtlasModelListener(JAtlasTree atlasTree, JProfilesPanel profilesPanel) { super(); @@ -55,4 +55,4 @@ public class AtlasModelListener implements TreeModelListener { public void treeStructureChanged(TreeModelEvent e) { changed(); } -} \ No newline at end of file +} diff --git a/src/main/java/mobac/gui/mapview/GridZoom.java b/mobac/src/main/java/mobac/gui/mapview/GridZoom.java similarity index 86% rename from src/main/java/mobac/gui/mapview/GridZoom.java rename to mobac/src/main/java/mobac/gui/mapview/GridZoom.java index 430fadd..b6a71a9 100644 --- a/src/main/java/mobac/gui/mapview/GridZoom.java +++ b/mobac/src/main/java/mobac/gui/mapview/GridZoom.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview; @@ -20,16 +20,16 @@ import mobac.utilities.I18nUtils; public class GridZoom { - private int zoom; - - public int getZoom() { - return zoom; - } + private final int zoom; public GridZoom(int zoom) { this.zoom = zoom; } + public int getZoom() { + return zoom; + } + @Override public String toString() { return String.format(I18nUtils.localizedStringForKey("map_ctrl_zoom_grid_prefix_fmt"), zoom); @@ -37,8 +37,9 @@ public class GridZoom { @Override public boolean equals(Object obj) { - if (!(obj instanceof GridZoom)) + if (!(obj instanceof GridZoom)) { return false; + } return ((GridZoom) obj).zoom == zoom; } diff --git a/src/main/java/mobac/gui/mapview/JMapViewer.java b/mobac/src/main/java/mobac/gui/mapview/JMapViewer.java similarity index 77% rename from src/main/java/mobac/gui/mapview/JMapViewer.java rename to mobac/src/main/java/mobac/gui/mapview/JMapViewer.java index d18680f..8bfc7a3 100644 --- a/src/main/java/mobac/gui/mapview/JMapViewer.java +++ b/mobac/src/main/java/mobac/gui/mapview/JMapViewer.java @@ -1,91 +1,82 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview; //License: GPL. Copyright 2008 by Jan Peter Stotz -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.Point; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.geom.Point2D; -import java.util.ConcurrentModificationException; -import java.util.LinkedList; -import java.util.List; - -import javax.swing.ImageIcon; -import javax.swing.JButton; -import javax.swing.JPanel; -import javax.swing.JSlider; -import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - import mobac.gui.mapview.interfaces.MapLayer; import mobac.gui.mapview.interfaces.MapTileLayer; import mobac.gui.mapview.interfaces.TileLoaderListener; import mobac.gui.mapview.layer.DefaultMapTileLayer; import mobac.gui.mapview.layer.MapGridLayer; import mobac.program.interfaces.MapSource; +import mobac.program.interfaces.MapSourceInitialDisplayPosition; import mobac.program.interfaces.MapSpace; +import mobac.utilities.I18nUtils; import mobac.utilities.Utilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Logger; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JSlider; +import javax.swing.SwingUtilities; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Point; +import java.awt.geom.Point2D; +import java.util.ConcurrentModificationException; +import java.util.LinkedList; +import java.util.List; /** - * - * Provides a simple panel that displays pre-rendered map tiles loaded from the OpenStreetMap project. - * + * Provides a simple panel that displays pre-rendered map tiles loaded from the + * OpenStreetMap project. + * * @author Jan Peter Stotz - * */ public class JMapViewer extends JPanel implements TileLoaderListener { - private static final long serialVersionUID = 1L; - - private static Logger log = Logger.getLogger(JMapViewer.class); - + public static final int MAX_ZOOM = 22; + public static final int MIN_ZOOM = 0; /** * Vectors for clock-wise tile painting */ - protected static final Point[] move = { new Point(1, 0), new Point(0, 1), new Point(-1, 0), new Point(0, -1) }; + protected static final Point[] move = {new Point(1, 0), new Point(0, 1), new Point(-1, 0), new Point(0, -1)}; + private static final long serialVersionUID = 1L; + private static final Logger log = LoggerFactory.getLogger(JMapViewer.class); - public static final int MAX_ZOOM = 22; - public static final int MIN_ZOOM = 0; + public final List mapLayers; + protected final TileLoader tileLoader; + protected final MemoryTileCache tileCache; - protected TileLoader tileLoader; - protected MemoryTileCache tileCache; protected MapSource mapSource; protected boolean usePlaceHolderTiles = true; - protected boolean mapMarkersVisible; protected MapGridLayer mapGridLayer = null; - protected List mapTileLayers; - public List mapLayers; - /** - * x- and y-position of the center of this map-panel on the world map denoted in screen pixel regarding the current - * zoom level. + * x- and y-position of the center of this map-panel on the world map denoted in + * screen pixel regarding the current zoom level. */ protected Point center = new Point(); @@ -98,12 +89,12 @@ public class JMapViewer extends JPanel implements TileLoaderListener { protected JButton zoomInButton; protected JButton zoomOutButton; - protected JobDispatcher jobDispatcher; + protected final JobDispatcher jobDispatcher; public JMapViewer(MapSource defaultMapSource, int downloadThreadCount) { super(); - mapTileLayers = new LinkedList(); - mapLayers = new LinkedList(); + mapTileLayers = new LinkedList<>(); + mapLayers = new LinkedList<>(); tileLoader = new TileLoader(this); tileCache = new MemoryTileCache(); jobDispatcher = JobDispatcher.getInstance(); @@ -120,11 +111,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener { zoomSlider.setOrientation(JSlider.VERTICAL); zoomSlider.setBounds(10, 10, 30, 150); zoomSlider.setOpaque(false); - zoomSlider.addChangeListener(new ChangeListener() { - public void stateChanged(ChangeEvent e) { - setZoom(zoomSlider.getValue()); - } - }); + zoomSlider.addChangeListener(e -> setZoom(zoomSlider.getValue())); add(zoomSlider); int size = 18; try { @@ -136,12 +123,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener { zoomInButton.setMargin(new Insets(0, 0, 0, 0)); } zoomInButton.setBounds(4, 155, size, size); - zoomInButton.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - zoomIn(); - } - }); + zoomInButton.addActionListener(e -> zoomIn()); add(zoomInButton); try { ImageIcon icon = Utilities.loadResourceImageIcon("minus.png"); @@ -152,18 +134,14 @@ public class JMapViewer extends JPanel implements TileLoaderListener { zoomOutButton.setMargin(new Insets(0, 0, 0, 0)); } zoomOutButton.setBounds(8 + size, 155, size, size); - zoomOutButton.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - zoomOut(); - } - }); + zoomOutButton.addActionListener(e -> zoomOut()); add(zoomOutButton); } /** - * Changes the map pane so that it is centered on the specified coordinate at the given zoom level. - * + * Changes the map pane so that it is centered on the specified coordinate at + * the given zoom level. + * * @param lat * latitude of the specified coordinate * @param lon @@ -176,11 +154,12 @@ public class JMapViewer extends JPanel implements TileLoaderListener { } /** - * Changes the map pane so that the specified coordinate at the given zoom level is displayed on the map at the - * screen coordinate mapPoint. - * + * Changes the map pane so that the specified coordinate at the given zoom level + * is displayed on the map at the screen coordinate mapPoint. + * * @param mapPoint - * point on the map denoted in pixels where the coordinate should be set + * point on the map denoted in pixels where the coordinate should be + * set * @param lat * latitude of the specified coordinate * @param lon @@ -201,8 +180,9 @@ public class JMapViewer extends JPanel implements TileLoaderListener { } public void setDisplayPosition(Point mapPoint, int x, int y, int zoom) { - if (zoom > mapSource.getMaxZoom() || zoom < MIN_ZOOM) + if (zoom > mapSource.getMaxZoom() || zoom < MIN_ZOOM) { return; + } // Get the plain tile number Point p = new Point(); @@ -213,10 +193,12 @@ public class JMapViewer extends JPanel implements TileLoaderListener { try { int oldZoom = this.zoom; this.zoom = zoom; - if (oldZoom != zoom) + if (oldZoom != zoom) { zoomChanged(oldZoom); - if (zoomSlider.getValue() != zoom) + } + if (zoomSlider.getValue() != zoom) { zoomSlider.setValue(zoom); + } } finally { setIgnoreRepaint(false); repaint(); @@ -224,9 +206,10 @@ public class JMapViewer extends JPanel implements TileLoaderListener { } /** - * Sets the displayed map pane and zoom level so that the two points (x1/y1) and (x2/y2) visible. Please note that - * the coordinates have to be specified regarding {@link #MAX_ZOOM}. - * + * Sets the displayed map pane and zoom level so that the two points (x1/y1) and + * (x2/y2) visible. Please note that the coordinates have to be specified + * regarding {@link #MAX_ZOOM}. + * * @param x1 * @param y1 * @param x2 @@ -275,7 +258,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener { /** * Calculates the position on the map of a given coordinate - * + * * @param lat * @param lon * @return point on the map or null if the point is not visible @@ -286,8 +269,9 @@ public class JMapViewer extends JPanel implements TileLoaderListener { int y = mapSpace.cLatToY(lat, zoom); x -= center.x - getWidth() / 2; y -= center.y - getHeight() / 2; - if (x < 0 || y < 0 || x > getWidth() || y > getHeight()) + if (x < 0 || y < 0 || x > getWidth() || y > getHeight()) { return null; + } return new Point(x, y); } @@ -328,15 +312,17 @@ public class JMapViewer extends JPanel implements TileLoaderListener { boolean start_top = diff_top < diff_bottom; if (start_top) { - if (start_left) + if (start_left) { iMove = 2; - else + } else { iMove = 3; + } } else { - if (start_left) + if (start_left) { iMove = 1; - else + } else { iMove = 0; + } } // calculate the visibility borders int x_min = -tileSize; int y_min = -tileSize; @@ -352,8 +338,9 @@ public class JMapViewer extends JPanel implements TileLoaderListener { while (painted) { painted = false; for (int i = 0; i < 4; i++) { - if (i % 2 == 0) + if (i % 2 == 0) { x++; + } for (int j = 0; j < x; j++) { if (x_min <= posx && posx <= x_max && y_min <= posy && posy <= y_max) { // tile is visible @@ -376,10 +363,11 @@ public class JMapViewer extends JPanel implements TileLoaderListener { int bottomRightY = topLeftY + getHeight(); try { for (MapLayer l : mapLayers) { - l.paint(this, (Graphics2D) g, zoom, topLeftX, topLeftY, bottomRightX, bottomRightY); + l.paint(this, g, zoom, topLeftX, topLeftY, bottomRightX, bottomRightY); } } catch (ConcurrentModificationException e) { - // This may happen when multiple GPX files are loaded at once and in the mean time the map view is + // This may happen when multiple GPX files are loaded at once and in the mean + // time the map view is // repainted. SwingUtilities.invokeLater(new Runnable() { public void run() { @@ -398,7 +386,7 @@ public class JMapViewer extends JPanel implements TileLoaderListener { /** * Moves the visible map pane. - * + * * @param x * horizontal movement in pixel. * @param y @@ -417,6 +405,11 @@ public class JMapViewer extends JPanel implements TileLoaderListener { return zoom; } + public void setZoom(int zoom) { + setZoom(zoom, new Point(getWidth() / 2, getHeight() / 2)); + repaint(); + } + /** * Increases the current zoom level by one */ @@ -446,30 +439,27 @@ public class JMapViewer extends JPanel implements TileLoaderListener { } public void setZoom(int zoom, Point mapPoint) { - if (zoom > mapSource.getMaxZoom() || zoom < mapSource.getMinZoom() || zoom == this.zoom) + if (zoom > mapSource.getMaxZoom() || zoom < mapSource.getMinZoom() || zoom == this.zoom) { return; + } Point2D.Double zoomPos = getPosition(mapPoint); jobDispatcher.cancelOutstandingJobs(); // Clearing outstanding load // requests setDisplayPositionByLatLon(mapPoint, zoomPos.x, zoomPos.y, zoom); } - public void setZoom(int zoom) { - setZoom(zoom, new Point(getWidth() / 2, getHeight() / 2)); - repaint(); - } - /** - * Every time the zoom level changes this method is called. Override it in derived implementations for adapting zoom - * dependent values. The new zoom level can be obtained via {@link #getZoom()}. - * + * Every time the zoom level changes this method is called. Override it in + * derived implementations for adapting zoom dependent values. The new zoom + * level can be obtained via {@link #getZoom()}. + * * @param oldZoom * the previous zoom level */ protected void zoomChanged(int oldZoom) { - zoomSlider.setToolTipText("Zoom level " + zoom); - zoomInButton.setToolTipText("Zoom to level " + (zoom + 1)); - zoomOutButton.setToolTipText("Zoom to level " + (zoom - 1)); + zoomSlider.setToolTipText(I18nUtils.localizedStringForKey("map_viewer_zoom_tooltip") + " " + zoom); + zoomInButton.setToolTipText(I18nUtils.localizedStringForKey("map_viewer_zoom_to_tooltip") + " " + (zoom + 1)); + zoomOutButton.setToolTipText(I18nUtils.localizedStringForKey("map_viewer_zoom_to_tooltip") + " " + (zoom - 1)); zoomOutButton.setEnabled(zoom > mapSource.getMinZoom()); zoomInButton.setEnabled(zoom < mapSource.getMaxZoom()); } @@ -479,8 +469,9 @@ public class JMapViewer extends JPanel implements TileLoaderListener { } public void setTileGridVisible(boolean tileGridVisible) { - if (isTileGridVisible() == tileGridVisible) + if (isTileGridVisible() == tileGridVisible) { return; + } if (tileGridVisible) { mapGridLayer = new MapGridLayer(); addMapTileLayers(mapGridLayer); @@ -495,16 +486,16 @@ public class JMapViewer extends JPanel implements TileLoaderListener { return mapMarkersVisible; } + public boolean getZoomContolsVisible() { + return zoomSlider.isVisible(); + } + public void setZoomContolsVisible(boolean visible) { zoomSlider.setVisible(visible); zoomInButton.setVisible(visible); zoomOutButton.setVisible(visible); } - public boolean getZoomContolsVisible() { - return zoomSlider.isVisible(); - } - public MemoryTileCache getTileImageCache() { return tileCache; } @@ -517,22 +508,36 @@ public class JMapViewer extends JPanel implements TileLoaderListener { return mapSource; } - public void setMapSource(MapSource mapSource) { - if (mapSource.getMaxZoom() > MAX_ZOOM) + public void setMapSource(MapSource newMapSource) { + if (newMapSource.getMaxZoom() > MAX_ZOOM) { throw new RuntimeException("Maximum zoom level too high"); - if (mapSource.getMinZoom() < MIN_ZOOM) - throw new RuntimeException("Minumim zoom level too low"); - this.mapSource = mapSource; - zoomSlider.setMinimum(mapSource.getMinZoom()); - zoomSlider.setMaximum(mapSource.getMaxZoom()); + } + if (newMapSource.getMinZoom() < MIN_ZOOM) { + throw new RuntimeException("Minimum zoom level too low"); + } + this.mapSource = newMapSource; + zoomSlider.setMinimum(newMapSource.getMinZoom()); + zoomSlider.setMaximum(newMapSource.getMaxZoom()); jobDispatcher.cancelOutstandingJobs(); - if (zoom > mapSource.getMaxZoom()) - setZoom(mapSource.getMaxZoom()); + if (zoom > newMapSource.getMaxZoom()) { + setZoom(newMapSource.getMaxZoom()); + } + + if (newMapSource instanceof MapSourceInitialDisplayPosition) { + MapSourceInitialDisplayPosition vp = (MapSourceInitialDisplayPosition) newMapSource; + if (vp.getInitialDisplayPositionX() != 0) { + setZoom(newMapSource.getMinZoom()); + setDisplayPosition(new Point(0, 0), vp.getInitialDisplayPositionX(), vp.getInitialDisplayPositionY(), + newMapSource.getMinZoom()); + } + } + mapTileLayers.clear(); - log.info("Map layer changed to: " + mapSource); - mapTileLayers.add(new DefaultMapTileLayer(this, mapSource)); - if (mapGridLayer != null) + log.info("Map layer changed to: " + newMapSource); + mapTileLayers.add(new DefaultMapTileLayer(this, newMapSource)); + if (mapGridLayer != null) { mapTileLayers.add(mapGridLayer); + } repaint(); } diff --git a/src/main/java/mobac/gui/mapview/JobDispatcher.java b/mobac/src/main/java/mobac/gui/mapview/JobDispatcher.java similarity index 55% rename from src/main/java/mobac/gui/mapview/JobDispatcher.java rename to mobac/src/main/java/mobac/gui/mapview/JobDispatcher.java index 18c3b16..3be1ace 100644 --- a/src/main/java/mobac/gui/mapview/JobDispatcher.java +++ b/mobac/src/main/java/mobac/gui/mapview/JobDispatcher.java @@ -1,23 +1,32 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview; //License: GPL. Copyright 2008 by Jan Peter Stotz +import mobac.program.interfaces.MapSourceCallerThreadInfo; +import mobac.program.interfaces.MapSourceListener; +import mobac.program.tilestore.berkeleydb.DelayedInterruptThread; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.RejectedExecutionHandler; @@ -25,23 +34,31 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import mobac.program.tilestore.berkeleydb.DelayedInterruptThread; - -import org.apache.log4j.Logger; - public class JobDispatcher implements ThreadFactory, RejectedExecutionHandler { - private static final Logger log = Logger.getLogger(JobDispatcher.class); + private static final Logger log = LoggerFactory.getLogger(JobDispatcher.class); private static final JobDispatcher INSTANCE = new JobDispatcher(); private static final int WORKER_THREAD_MAX_COUNT = 5; /** - * Specifies the time span in seconds that a worker thread waits for new jobs to perform. If the time span has - * elapsed the worker thread terminates itself. Only the first worker thread works differently, it ignores the - * timeout and will never terminate itself. + * Specifies the time span in seconds that a worker thread waits for new jobs to + * perform. If the time span has elapsed the worker thread terminates itself. + * Only the first worker thread works differently, it ignores the timeout and + * will never terminate itself. */ private static final int WORKER_THREAD_TIMEOUT = 30; + private final BlockingQueue jobQueue; + private final ThreadPoolExecutor executor; + private final List mapSourceListeners = Collections.synchronizedList(new LinkedList<>()); + private int WORKER_THREAD_ID = 1; + + private JobDispatcher() { + jobQueue = new LinkedBlockingQueue(); + executor = new ThreadPoolExecutor(WORKER_THREAD_MAX_COUNT, WORKER_THREAD_MAX_COUNT, WORKER_THREAD_TIMEOUT, + TimeUnit.SECONDS, jobQueue, this, this); + executor.allowCoreThreadTimeOut(true); + } /** * @return the singleton instance of the {@link JobDispatcher} @@ -50,12 +67,6 @@ public class JobDispatcher implements ThreadFactory, RejectedExecutionHandler { return INSTANCE; } - private int WORKER_THREAD_ID = 1; - - private final BlockingQueue jobQueue; - - private final ThreadPoolExecutor executor; - /** * Removes all jobs from the queue that are currently not being processed. */ @@ -63,13 +74,6 @@ public class JobDispatcher implements ThreadFactory, RejectedExecutionHandler { jobQueue.clear(); } - private JobDispatcher() { - jobQueue = new LinkedBlockingQueue(); - executor = new ThreadPoolExecutor(WORKER_THREAD_MAX_COUNT, WORKER_THREAD_MAX_COUNT, WORKER_THREAD_TIMEOUT, - TimeUnit.SECONDS, jobQueue, this, this); - executor.allowCoreThreadTimeOut(true); - } - public void addJob(Runnable job) { executor.execute(job); } @@ -79,12 +83,54 @@ public class JobDispatcher implements ThreadFactory, RejectedExecutionHandler { synchronized (this) { id = WORKER_THREAD_ID++; } - log.trace("New map preview worker thread created with id=" + id); - return new DelayedInterruptThread(r, "Map preview thread " + id); + log.trace("New map preview worker thread created with id={}", id); + return new MapPreviewThread(r, "Map preview thread " + id); } public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { log.error("Map preview job rejected: " + r); } + public void addMapSourceListener(MapSourceListener listener) { + mapSourceListeners.add(listener); + } + public boolean removeMapSourceListener(MapSourceListener listener) { + return mapSourceListeners.remove(listener); + } + + public class MapPreviewThread extends DelayedInterruptThread + implements + MapSourceCallerThreadInfo, + MapSourceListener { + + public MapPreviewThread(Runnable target, String name) { + super(target, name); + } + + @Override + public boolean isMapPreviewThread() { + return true; + } + + @Override + public void tileDownloadStarted(String tileUrl) { + for (MapSourceListener listener : mapSourceListeners) { + listener.tileDownloadStarted(tileUrl); + } + } + + @Override + public void tileDownloaded(int size) { + for (MapSourceListener listener : mapSourceListeners) { + listener.tileDownloaded(size); + } + } + + @Override + public void tileLoadedFromCache(int size) { + for (MapSourceListener listener : mapSourceListeners) { + listener.tileLoadedFromCache(size); + } + } + } } diff --git a/src/main/java/mobac/gui/mapview/MemoryTileCache.java b/mobac/src/main/java/mobac/gui/mapview/MemoryTileCache.java similarity index 81% rename from src/main/java/mobac/gui/mapview/MemoryTileCache.java rename to mobac/src/main/java/mobac/gui/mapview/MemoryTileCache.java index 133967f..7bd1bea 100644 --- a/src/main/java/mobac/gui/mapview/MemoryTileCache.java +++ b/mobac/src/main/java/mobac/gui/mapview/MemoryTileCache.java @@ -1,23 +1,31 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview; //License: GPL. Copyright 2008 by Jan Peter Stotz +import mobac.gui.mapview.Tile.TileState; +import mobac.program.interfaces.MapSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.management.Notification; +import javax.management.NotificationBroadcaster; +import javax.management.NotificationListener; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryNotificationInfo; @@ -25,19 +33,11 @@ import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryUsage; import java.util.Hashtable; -import javax.management.Notification; -import javax.management.NotificationBroadcaster; -import javax.management.NotificationListener; - -import mobac.gui.mapview.Tile.TileState; -import mobac.program.interfaces.MapSource; - -import org.apache.log4j.Logger; - /** - * {@link TileImageCache} implementation that stores all {@link Tile} objects in memory up to a certain limit ( - * {@link #getCacheSize()}). If the limit is exceeded the least recently used {@link Tile} objects will be deleted. - * + * Cache that stores all {@link Tile} objects in memory up to a certain limit ( + * {@link #getCacheSize()}). If the limit is exceeded the least recently used + * {@link Tile} objects will be deleted. + * * @author Jan Peter Stotz * @author r_x */ @@ -58,10 +58,10 @@ public class MemoryTileCache implements NotificationListener { protected CacheLinkedListElement lruTiles; public MemoryTileCache() { - log = Logger.getLogger(this.getClass()); + log = LoggerFactory.getLogger(this.getClass()); hashtable = new Hashtable(cacheSize); lruTiles = new CacheLinkedListElement(); - + cacheSize = 500; MemoryMXBean mbean = ManagementFactory.getMemoryMXBean(); NotificationBroadcaster emitter = (NotificationBroadcaster) mbean; @@ -76,18 +76,21 @@ public class MemoryTileCache implements NotificationListener { } /** - * In case we are running out of memory we free half of the cached down to a minimum of 25 cached tiles. + * In case we are running out of memory we free half of the cached down to a + * minimum of 25 cached tiles. */ public void handleNotification(Notification notification, Object handback) { - log.trace("Memory notification: " + notification.toString()); - if (!MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED.equals(notification.getType())) + log.trace("Memory notification: {}", notification); + if (!MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED.equals(notification.getType())) { return; + } synchronized (lruTiles) { int count_half = lruTiles.getElementCount() / 2; count_half = Math.max(25, count_half); - if (lruTiles.getElementCount() <= count_half) + if (lruTiles.getElementCount() <= count_half) { return; - log.warn("memory low - freeing cached tiles: " + lruTiles.getElementCount() + " -> " + count_half); + } + log.warn("memory low - freeing cached tiles: {} -> {}", lruTiles.getElementCount(), count_half); try { while (lruTiles.getElementCount() > count_half) { removeEntry(lruTiles.getLastElement()); @@ -102,18 +105,21 @@ public class MemoryTileCache implements NotificationListener { CacheEntry entry = createCacheEntry(tile); hashtable.put(tile.getKey(), entry); lruTiles.addFirst(entry); - if (hashtable.size() > cacheSize) + if (hashtable.size() > cacheSize) { removeOldEntries(); + } } public Tile getTile(MapSource source, int x, int y, int z) { CacheEntry entry = hashtable.get(Tile.getTileKey(source, x, y, z)); - if (entry == null) + if (entry == null) { return null; + } // We don't care about placeholder tiles and hourglass image tiles, the // important tiles are the loaded ones - if (entry.tile.getTileState() == TileState.TS_LOADED) + if (entry.tile.getTileState() == TileState.TS_LOADED) { lruTiles.moveElementToFirstPos(entry); + } return entry.tile; } @@ -161,18 +167,20 @@ public class MemoryTileCache implements NotificationListener { /** * Changes the maximum number of {@link Tile} objects that this cache holds. - * + * * @param cacheSize * new maximum number of tiles */ public void setCacheSize(int cacheSize) { this.cacheSize = cacheSize; - if (hashtable.size() > cacheSize) + if (hashtable.size() > cacheSize) { removeOldEntries(); + } } /** - * Linked list element holding the {@link Tile} and links to the {@link #next} and {@link #prev} item in the list. + * Linked list element holding the {@link Tile} and links to the {@link #next} + * and {@link #prev} item in the list. */ protected static class CacheEntry { Tile tile; @@ -199,9 +207,10 @@ public class MemoryTileCache implements NotificationListener { } /** - * Special implementation of a double linked list for {@link CacheEntry} elements. It supports element removal in - * constant time - in difference to the Java implementation which needs O(n). - * + * Special implementation of a double linked list for {@link CacheEntry} + * elements. It supports element removal in constant time - in difference to the + * Java implementation which needs O(n). + * * @author Jan Peter Stotz */ protected static class CacheLinkedListElement { @@ -221,8 +230,9 @@ public class MemoryTileCache implements NotificationListener { /** * Add the element to the head of the list. - * - * @param new element to be added + * + * @param element + * new element to be added */ public synchronized void addFirst(CacheEntry element) { if (elementCount == 0) { @@ -241,7 +251,7 @@ public class MemoryTileCache implements NotificationListener { /** * Removes the specified elemntent form the list. - * + * * @param element * to be removed */ @@ -252,18 +262,21 @@ public class MemoryTileCache implements NotificationListener { if (element.prev != null) { element.prev.next = element.next; } - if (element == firstElement) + if (element == firstElement) { firstElement = element.next; - if (element == lastElement) + } + if (element == lastElement) { lastElement = element.prev; + } element.next = null; element.prev = null; elementCount--; } public synchronized void moveElementToFirstPos(CacheEntry entry) { - if (firstElement == entry) + if (firstElement == entry) { return; + } removeEntry(entry); addFirst(entry); } diff --git a/src/main/java/mobac/gui/mapview/PreviewMap.java b/mobac/src/main/java/mobac/gui/mapview/PreviewMap.java similarity index 73% rename from src/main/java/mobac/gui/mapview/PreviewMap.java rename to mobac/src/main/java/mobac/gui/mapview/PreviewMap.java index 89a1a2d..bafd132 100644 --- a/src/main/java/mobac/gui/mapview/PreviewMap.java +++ b/mobac/src/main/java/mobac/gui/mapview/PreviewMap.java @@ -1,21 +1,42 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview; +import mobac.gui.MainGUI; +import mobac.gui.mapview.controller.DefaultMapController; +import mobac.gui.mapview.controller.JMapController; +import mobac.gui.mapview.controller.MapKeyboardController; +import mobac.gui.mapview.controller.RectangleSelectionMapController; +import mobac.gui.mapview.interfaces.MapEventListener; +import mobac.mapsources.MapSourcesManager; +import mobac.program.interfaces.MapSource; +import mobac.program.interfaces.MapSourceTextAttribution; +import mobac.program.interfaces.MapSpace; +import mobac.program.interfaces.RefreshableMapSource; +import mobac.program.model.Bookmark; +import mobac.program.model.EastNorthCoordinate; +import mobac.program.model.MapSelection; +import mobac.program.model.MercatorPixelCoordinate; +import mobac.program.model.Settings; +import mobac.utilities.I18nUtils; +import mobac.utilities.MyMath; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.Color; import java.awt.Font; import java.awt.Graphics; @@ -25,68 +46,43 @@ import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.util.LinkedList; -import mobac.gui.mapview.controller.DefaultMapController; -import mobac.gui.mapview.controller.JMapController; -import mobac.gui.mapview.controller.MapKeyboardController; -import mobac.gui.mapview.controller.RectangleSelectionMapController; -import mobac.gui.mapview.interfaces.MapEventListener; -import mobac.mapsources.MapSourcesManager; -import mobac.program.interfaces.MapSource; -import mobac.program.interfaces.MapSourceTextAttribution; -import mobac.program.interfaces.MapSpace; -import mobac.program.model.Bookmark; -import mobac.program.model.EastNorthCoordinate; -import mobac.program.model.MapSelection; -import mobac.program.model.MercatorPixelCoordinate; -import mobac.program.model.Settings; -import mobac.utilities.I18nUtils; -import mobac.utilities.MyMath; - -import org.apache.log4j.Logger; - public class PreviewMap extends JMapViewer { - private static final long serialVersionUID = 1L; - public static final Color GRID_COLOR = new Color(200, 20, 20, 130); public static final Color SEL_COLOR = new Color(0.9f, 0.7f, 0.7f, 0.6f); public static final Color MAP_COLOR = new Color(1.0f, 0.84f, 0.0f, 0.4f); - public static final int MAP_CONTROLLER_RECTANGLE_SELECT = 0; public static final int MAP_CONTROLLER_GPX = 1; - protected static final Font LOADING_FONT = new Font("Sans Serif", Font.BOLD, 30); - - private static Logger log = Logger.getLogger(PreviewMap.class); - - /** - * Interactive map selection max/min pixel coordinates regarding zoom level MAX_ZOOM - */ - private Point iSelectionMin; - private Point iSelectionMax; - - /** - * Map selection max/min pixel coordinates regarding zoom level MAX_ZOOM with respect to the grid zoom. - */ - private Point gridSelectionStart; - private Point gridSelectionEnd; - - /** - * Pre-painted transparent tile with grid lines on it. This makes painting the grid a lot faster in difference to - * painting each line or rectangle if the grid zoom is much higher that the current zoom level. - */ - private BufferedImage gridTile = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB); - - private int gridZoom = -1; - private int gridSize; - - protected LinkedList mapEventListeners = new LinkedList(); - + private static final long serialVersionUID = 1L; + private static final Logger log = LoggerFactory.getLogger(PreviewMap.class); + public final Ruler ruler = new Ruler(this); + private final WgsGrid wgsGrid = new WgsGrid(Settings.getInstance().wgsGrid, this); + public boolean isMeasuring = false; + protected LinkedList mapEventListeners = new LinkedList<>(); protected JMapController mapKeyboardController; protected JMapController mapSelectionController; protected DefaultMapController defaultMapController; - - private final WgsGrid wgsGrid = new WgsGrid(Settings.getInstance().wgsGrid, this); + /** + * Interactive map selection max/min pixel coordinates regarding zoom level + * MAX_ZOOM + */ + private Point iSelectionMin; + private Point iSelectionMax; + /** + * Map selection max/min pixel coordinates regarding zoom level + * MAX_ZOOM with respect to the grid zoom. + */ + private Point gridSelectionStart; + private Point gridSelectionEnd; + /** + * Pre-painted transparent tile with grid lines on it. This makes painting the + * grid a lot faster in difference to painting each line or rectangle if the + * grid zoom is much higher that the current zoom level. + */ + private BufferedImage gridTile = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB); + private int gridZoom = -1; + private int gridSize; public PreviewMap() { super(MapSourcesManager.getInstance().getDefaultMapSource(), 5); @@ -122,8 +118,9 @@ public class PreviewMap extends JMapViewer { public void settingsLoad() { Settings settings = Settings.getInstance(); MapSource mapSource = MapSourcesManager.getInstance().getSourceByName(settings.mapviewMapSource); - if (mapSource != null) + if (mapSource != null) { setMapSource(mapSource); + } EastNorthCoordinate c = settings.mapviewCenterCoordinate; gridZoom = settings.mapviewGridZoom; setDisplayPositionByLatLon(c, settings.mapviewZoom); @@ -132,27 +129,41 @@ public class PreviewMap extends JMapViewer { @Override public void setMapSource(MapSource newMapSource) { - if (newMapSource.equals(mapSource)) + setMapSource(newMapSource, false); + } + + public void setMapSource(MapSource newMapSource, boolean force) { + if (newMapSource == null || (!force && newMapSource.equals(mapSource))) { return; - log.trace("Preview map source changed from " + mapSource + " to " + newMapSource); + } + log.trace("Preview map source changed from {} to {}", mapSource, newMapSource); super.setMapSource(newMapSource); - if (mapEventListeners == null) + if (mapEventListeners == null) { return; - for (MapEventListener listener : mapEventListeners) + } + for (MapEventListener listener : mapEventListeners) { listener.mapSourceChanged(mapSource); + } } protected void zoomChanged(int oldZoom) { - log.trace("Preview map zoom changed from " + oldZoom + " to " + zoom); - if (mapEventListeners != null) - for (MapEventListener listener : mapEventListeners) + log.trace("Preview map zoom changed from {} to {}", oldZoom, zoom); + if (mapEventListeners != null) { + for (MapEventListener listener : mapEventListeners) { listener.zoomChanged(zoom); + } + } updateGridValues(); } + public int getGridZoom() { + return gridZoom; + } + public void setGridZoom(int gridZoom) { - if (gridZoom == this.gridZoom) + if (gridZoom == this.gridZoom) { return; + } this.gridZoom = gridZoom; updateGridValues(); applyGridOnSelection(); @@ -160,17 +171,19 @@ public class PreviewMap extends JMapViewer { repaint(); } - public int getGridZoom() { - return gridZoom; + public void setIsMeasuring(Boolean val) { + isMeasuring = val; + MainGUI.getMainGUI().setEnableLeftPanel(!isMeasuring); } /** - * Updates the gridSize and the gridTile. This method has to called if - * mapSource or zoom as been changed. + * Updates the gridSize and the gridTile. This method + * has to called if mapSource or zoom as been changed. */ protected void updateGridValues() { - if (gridZoom < 0) + if (gridZoom < 0) { return; + } int zoomToGridZoom = zoom - gridZoom; int tileSize = mapSource.getMapSpace().getTileSize(); if (zoomToGridZoom > 0) { @@ -186,10 +199,12 @@ public class PreviewMap extends JMapViewer { alpha = Math.max(0, alpha); alpha = Math.min(130, alpha); g.setColor(new Color(200, 20, 20, alpha)); - for (int x = 0; x < tileSize; x += gridSize) + for (int x = 0; x < tileSize; x += gridSize) { g.drawLine(x, 0, x, 255); - for (int y = 0; y < tileSize; y += gridSize) + } + for (int y = 0; y < tileSize; y += gridSize) { g.drawLine(0, y, 255, y); + } } gridTile = newGridTile; } @@ -202,8 +217,9 @@ public class PreviewMap extends JMapViewer { graphics.drawString(I18nUtils.localizedStringForKey("map_loading_wait"), 100, 100); return; } - if (mapSource == null) + if (mapSource == null) { return; + } Graphics2D g = (Graphics2D) graphics; super.paintComponent(g); @@ -237,31 +253,33 @@ public class PreviewMap extends JMapViewer { } } } - if (gridSelectionStart != null && gridSelectionEnd != null) { - // Draw the selection rectangle widened by the current grid - int zoomDiff = MAX_ZOOM - zoom; - int x_min = (gridSelectionStart.x >> zoomDiff) - tlc.x; - int y_min = (gridSelectionStart.y >> zoomDiff) - tlc.y; - int x_max = (gridSelectionEnd.x >> zoomDiff) - tlc.x; - int y_max = (gridSelectionEnd.y >> zoomDiff) - tlc.y; + if (!isMeasuring) { + if (gridSelectionStart != null && gridSelectionEnd != null) { + // Draw the selection rectangle widened by the current grid + int zoomDiff = MAX_ZOOM - zoom; + int x_min = (gridSelectionStart.x >> zoomDiff) - tlc.x; + int y_min = (gridSelectionStart.y >> zoomDiff) - tlc.y; + int x_max = (gridSelectionEnd.x >> zoomDiff) - tlc.x; + int y_max = (gridSelectionEnd.y >> zoomDiff) - tlc.y; - int w = x_max - x_min + 1; - int h = y_max - y_min + 1; - g.setColor(SEL_COLOR); - g.fillRect(x_min, y_min, w, h); - } - if (iSelectionMin != null && iSelectionMax != null) { - // Draw the selection rectangle exactly as it has been specified by the user - int zoomDiff = MAX_ZOOM - zoom; - int x_min = (iSelectionMin.x >> zoomDiff) - tlc.x; - int y_min = (iSelectionMin.y >> zoomDiff) - tlc.y; - int x_max = (iSelectionMax.x >> zoomDiff) - tlc.x; - int y_max = (iSelectionMax.y >> zoomDiff) - tlc.y; + int w = x_max - x_min + 1; + int h = y_max - y_min + 1; + g.setColor(SEL_COLOR); + g.fillRect(x_min, y_min, w, h); + } + if (iSelectionMin != null && iSelectionMax != null) { + // Draw the selection rectangle exactly as it has been specified by the user + int zoomDiff = MAX_ZOOM - zoom; + int x_min = (iSelectionMin.x >> zoomDiff) - tlc.x; + int y_min = (iSelectionMin.y >> zoomDiff) - tlc.y; + int x_max = (iSelectionMax.x >> zoomDiff) - tlc.x; + int y_max = (iSelectionMax.y >> zoomDiff) - tlc.y; - int w = x_max - x_min + 1; - int h = y_max - y_min + 1; - g.setColor(GRID_COLOR); - g.drawRect(x_min, y_min, w, h); + int w = x_max - x_min + 1; + int h = y_max - y_min + 1; + g.setColor(GRID_COLOR); + g.drawRect(x_min, y_min, w, h); + } } if (mapSource instanceof MapSourceTextAttribution) { MapSourceTextAttribution ta = (MapSourceTextAttribution) mapSource; @@ -280,6 +298,11 @@ public class PreviewMap extends JMapViewer { wgsGrid.paintWgsGrid(g, mapSource.getMapSpace(), tlc, zoom); } ScaleBar.paintScaleBar(this, g, mapSource.getMapSpace(), tlc, zoom); + + // if measure tool is paused, keep the path overlay + if (isMeasuring || ruler.segments.size() > 0) { + ruler.paint(this, g, tlc, zoom); + } } public Bookmark getPositionBookmark() { @@ -293,7 +316,8 @@ public class PreviewMap extends JMapViewer { } /** - * @return Coordinate of the point in the center of the currently displayed map region + * @return Coordinate of the point in the center of the currently displayed map + * region */ public EastNorthCoordinate getCenterCoordinate() { MapSpace mapSpace = mapSource.getMapSpace(); @@ -303,16 +327,18 @@ public class PreviewMap extends JMapViewer { } /** - * @return Coordinate of the top left corner visible regarding the current map source (pixel) + * @return Coordinate of the top left corner visible regarding the current map + * source (pixel) */ public Point getTopLeftCoordinate() { return new Point(center.x - (getWidth() / 2), center.y - (getHeight() / 2)); } public void zoomTo(MapSelection ms) { - if (!ms.isAreaSelected()) + if (!ms.isAreaSelected()) { return; - log.trace("Setting selection to: " + ms); + } + log.trace("Setting selection to: {}", ms); Point max = ms.getBottomRightPixelCoordinate(MAX_ZOOM); Point min = ms.getTopLeftPixelCoordinate(MAX_ZOOM); setDisplayToFitPixelCoordinates(max.x, max.y, min.x, min.y); @@ -320,12 +346,12 @@ public class PreviewMap extends JMapViewer { /** * Zooms to the specified {@link MapSelection} and sets the selection to it; - * + * * @param ms * @param notifyListeners */ public void setSelectionAndZoomTo(MapSelection ms, boolean notifyListeners) { - log.trace("Setting selection to: " + ms); + log.trace("Setting selection to: {}", ms); Point max = ms.getBottomRightPixelCoordinate(MAX_ZOOM); Point min = ms.getTopLeftPixelCoordinate(MAX_ZOOM); setDisplayToFitPixelCoordinates(max.x, max.y, min.x, min.y); @@ -335,11 +361,12 @@ public class PreviewMap extends JMapViewer { } /** - * * @param pStart - * x/y tile coordinate of the top left tile regarding the current zoom level + * x/y tile coordinate of the top left tile regarding the current + * zoom level * @param pEnd - * x/y tile coordinate of the bottom right tile regarding the current zoom level + * x/y tile coordinate of the bottom right tile regarding the current + * zoom level * @param notifyListeners */ public void setSelectionByTileCoordinate(Point pStart, Point pEnd, boolean notifyListeners) { @@ -347,9 +374,10 @@ public class PreviewMap extends JMapViewer { } /** - * Sets the rectangular selection to the absolute tile coordinates pStart and pEnd - * regarding the zoom-level cZoom. - * + * Sets the rectangular selection to the absolute tile coordinates + * pStart and pEnd regarding the zoom-level + * cZoom. + * * @param cZoom * @param pStart * @param pEnd @@ -367,7 +395,8 @@ public class PreviewMap extends JMapViewer { Point pNewStart = new Point(); Point pNewEnd = new Point(); int mapMaxCoordinate = mapSource.getMapSpace().getMaxPixels(cZoom) - 1; - // Sort x/y coordinate of points so that pNewStart < pnewEnd and limit selection to map size + // Sort x/y coordinate of points so that pNewStart < pnewEnd and limit selection + // to map size pNewStart.x = Math.max(0, Math.min(mapMaxCoordinate, Math.min(pStart.x, pEnd.x))); pNewStart.y = Math.max(0, Math.min(mapMaxCoordinate, Math.min(pStart.y, pEnd.y))); pNewEnd.x = Math.max(0, Math.min(mapMaxCoordinate, Math.max(pStart.x, pEnd.x))); @@ -388,8 +417,9 @@ public class PreviewMap extends JMapViewer { updateGridValues(); applyGridOnSelection(); - if (notifyListeners) + if (notifyListeners) { updateMapSelection(); + } repaint(); } @@ -400,8 +430,9 @@ public class PreviewMap extends JMapViewer { return; } - if (iSelectionMin == null || iSelectionMax == null) + if (iSelectionMin == null || iSelectionMax == null) { return; + } int gridZoomDiff = MAX_ZOOM - gridZoom; int gridFactor = mapSource.getMapSpace().getTileSize() << gridZoomDiff; @@ -422,21 +453,24 @@ public class PreviewMap extends JMapViewer { /** * Notifies all registered {@link MapEventListener} of a - * {@link MapEventListener#selectionChanged(MercatorPixelCoordinate, MercatorPixelCoordinate)} event. + * {@link MapEventListener#selectionChanged(MercatorPixelCoordinate, MercatorPixelCoordinate)} + * event. */ public void updateMapSelection() { int x_min, y_min, x_max, y_max; if (gridZoom >= 0) { - if (gridSelectionStart == null || gridSelectionEnd == null) + if (gridSelectionStart == null || gridSelectionEnd == null) { return; + } x_min = gridSelectionStart.x; y_min = gridSelectionStart.y; x_max = gridSelectionEnd.x; y_max = gridSelectionEnd.y; } else { - if (iSelectionMin == null || iSelectionMax == null) + if (iSelectionMin == null || iSelectionMax == null) { return; + } x_min = iSelectionMin.x; y_min = iSelectionMin.y; x_max = iSelectionMax.x; @@ -446,8 +480,9 @@ public class PreviewMap extends JMapViewer { MercatorPixelCoordinate max = new MercatorPixelCoordinate(mapSource.getMapSpace(), x_max, y_max, MAX_ZOOM); // log.debug("sel min: [" + min + "]"); // log.debug("sel max: [" + max + "]"); - for (MapEventListener listener : mapEventListeners) + for (MapEventListener listener : mapEventListeners) { listener.selectionChanged(max, min); + } } public void addMapEventListener(MapEventListener l) { @@ -467,11 +502,45 @@ public class PreviewMap extends JMapViewer { } /** - * Clears the in-memory tile cache and performs a repaint which causes a reload of all displayed tiles (from disk or - * if not present from the map source via network). + * Clears the in-memory tile cache and performs a repaint which causes a reload + * of all displayed tiles (from disk or if not present from the map source via + * network). */ public void refreshMap() { tileCache.clear(); + if (mapSource instanceof RefreshableMapSource) { + ((RefreshableMapSource) mapSource).refresh(); + } + repaint(); + } + + public void runRuler(String action) { + if (action == "toggle") { + action = isMeasuring ? "stop" : "start"; + } + + switch (action) { + case "clearkb" : // double clear disables measure mode (keyboard only) + if (ruler.segments.size() == 0) { + setIsMeasuring(false); + } + case "clear" : + break; + + case "start" : + setIsMeasuring(true); + break; + + case "stop" : + setIsMeasuring(false); + return; + + case "exit" : + setIsMeasuring(false); + break; + } + + ruler.segments.clear(); repaint(); } @@ -487,13 +556,15 @@ public class PreviewMap extends JMapViewer { } /** - * Sets a new mapSelectionController. Previous controller are disabled and removed. - * + * Sets a new mapSelectionController. Previous controller are disabled and + * removed. + * * @param mapSelectionController */ public void setMapSelectionController(JMapController mapSelectionController) { - if (this.mapSelectionController != null) + if (this.mapSelectionController != null) { this.mapSelectionController.disable(); + } this.mapSelectionController = mapSelectionController; mapSelectionController.enable(); for (MapEventListener listener : mapEventListeners) { diff --git a/mobac/src/main/java/mobac/gui/mapview/Ruler.java b/mobac/src/main/java/mobac/gui/mapview/Ruler.java new file mode 100644 index 0000000..ab552a6 --- /dev/null +++ b/mobac/src/main/java/mobac/gui/mapview/Ruler.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.gui.mapview; + +import mobac.program.interfaces.MapSpace; +import mobac.program.model.Settings; +import mobac.program.model.UnitSystem; + +import javax.swing.JComponent; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.geom.Point2D; +import java.util.ArrayList; + +// License: GPL. Copyright 2019 by Pierre Reinert +// Measurement tool + +public class Ruler { + private static final Font font = new Font("SansSerif", Font.BOLD, 12); + private final PreviewMap map; + public ArrayList segments = new ArrayList<>(); + + public Ruler(PreviewMap map) { + super(); + this.map = map; + } + + public Point2D.Double first() { + return segments.get(0); + } + + public Point2D.Double last() { + return segments.get(segments.size() - 1); + } + + public void remove() { + if (segments.size() > 0) { + segments.remove(segments.size() - 1); + } + } + + public void insert(Point pix) { + int zoom = map.getZoom(); + double lon = map.getMapSource().getMapSpace().cXToLon(pix.x, zoom); + double lat = map.getMapSource().getMapSpace().cYToLat(pix.y, zoom); + segments.add(new Point2D.Double(lon, lat)); + if (segments.size() == 1) { + insert(pix); // initial 0m segment + } + } + + public void paint(JComponent c, Graphics2D g, Point tlc, int zoom) { + double dist = 0d; + MapSpace mapspace = map.getMapSource().getMapSpace(); + g.setStroke(new BasicStroke(3.0f)); + g.setColor(Color.RED); + if (segments.size() <= 1) { + drawDistance(g, 0d); + return; + } + + Point2D.Double last = null; + for (Point2D.Double p : segments) { + if (last != null) { + g.drawLine(mapspace.cLonToX(last.x, zoom) - tlc.x, mapspace.cLatToY(last.y, zoom) - tlc.y, + mapspace.cLonToX(p.x, zoom) - tlc.x, mapspace.cLatToY(p.y, zoom) - tlc.y); + dist += mapspace.distance(last.y, last.x, p.y, p.x); + } + last = p; + } + + drawDistance(g, dist); + } + + public void drawDistance(Graphics2D g, double dist) { + UnitSystem unitSystem = Settings.getInstance().unitSystem; + String unit = unitSystem.unitLarge; + String value = String.format("%.2f %s", dist, unit); + + g.setBackground(Color.WHITE); + g.setColor(Color.BLUE); + g.clearRect(87, 80, 85, 30); + g.drawRect(87, 80, 85, 30); + g.setFont(font); + g.drawString(value, 100, 100); + } +} diff --git a/src/main/java/mobac/gui/mapview/ScaleBar.java b/mobac/src/main/java/mobac/gui/mapview/ScaleBar.java similarity index 92% rename from src/main/java/mobac/gui/mapview/ScaleBar.java rename to mobac/src/main/java/mobac/gui/mapview/ScaleBar.java index 7e6e6f9..0601953 100644 --- a/src/main/java/mobac/gui/mapview/ScaleBar.java +++ b/mobac/src/main/java/mobac/gui/mapview/ScaleBar.java @@ -1,21 +1,27 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview; +import mobac.program.interfaces.MapSpace; +import mobac.program.model.Settings; +import mobac.program.model.UnitSystem; +import mobac.utilities.MyMath; + +import javax.swing.JComponent; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; @@ -24,13 +30,6 @@ import java.awt.Point; import java.awt.Rectangle; import java.awt.Stroke; -import javax.swing.JComponent; - -import mobac.program.interfaces.MapSpace; -import mobac.program.model.Settings; -import mobac.program.model.UnitSystem; -import mobac.utilities.MyMath; - /** * Simple scale bar showing the map scale using the selected unit system. */ @@ -87,7 +86,7 @@ public class ScaleBar { g.fillRect(posX, posY - 10, w2, 20); g.setColor(Color.BLACK); g.drawRect(posX, posY - 10, w2, 20); - String value = Integer.toString((int) dist2) + " " + unit; + String value = ((int) dist2) + " " + unit; g.setFont(FONT); g.drawString(value, posX + 10, posY + 4); } diff --git a/src/main/java/mobac/gui/mapview/Tile.java b/mobac/src/main/java/mobac/gui/mapview/Tile.java similarity index 79% rename from src/main/java/mobac/gui/mapview/Tile.java rename to mobac/src/main/java/mobac/gui/mapview/Tile.java index 534503d..53fb6ca 100644 --- a/src/main/java/mobac/gui/mapview/Tile.java +++ b/mobac/src/main/java/mobac/gui/mapview/Tile.java @@ -1,23 +1,29 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview; //License: GPL. Copyright 2008 by Jan Peter Stotz +import mobac.program.interfaces.MapSource; +import mobac.utilities.Utilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.imageio.ImageIO; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; @@ -27,18 +33,16 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import javax.imageio.ImageIO; - -import mobac.program.interfaces.MapSource; -import mobac.utilities.Utilities; - /** - * Holds one map tile. Additionally the code for loading the tile image and painting it is also included in this class. - * + * Holds one map tile. Additionally the code for loading the tile image and + * painting it is also included in this class. + * * @author Jan Peter Stotz */ public class Tile { + private static final Logger log = LoggerFactory.getLogger(Tile.class); + /** * Hourglass image that is displayed until a map tile has been loaded */ @@ -55,21 +59,19 @@ public class Tile { } } - public enum TileState { - TS_NEW, TS_LOADING, TS_LOADED, TS_ERROR - }; - protected MapSource mapSource; + protected int xtile; protected int ytile; protected int zoom; protected BufferedImage image; protected String key; protected TileState tileState = TileState.TS_NEW; + protected String errorMessage; /** * Creates a tile with empty image. - * + * * @param mapSource * @param xtile * @param ytile @@ -90,9 +92,14 @@ public class Tile { this.image = image; } + public static String getTileKey(MapSource source, int xtile, int ytile, int zoom) { + return zoom + "/" + xtile + "/" + ytile + "@" + source.getName(); + } + /** - * Tries to get tiles of a lower or higher zoom level (one or two level difference) from cache and use it as a - * placeholder until the tile has been loaded. + * Tries to get tiles of a lower or higher zoom level (one or two level + * difference) from cache and use it as a placeholder until the tile has been + * loaded. */ public void loadPlaceholderFromCache(MemoryTileCache cache) { int tileSize = mapSource.getMapSpace().getTileSize(); @@ -171,10 +178,6 @@ public class Tile { return zoom; } - public BufferedImage getImage() { - return image; - } - public void setImage(BufferedImage image) { this.image = image; } @@ -184,6 +187,24 @@ public class Tile { tileState = TileState.TS_ERROR; } + public void setErrorImage(byte[] imageData) { + try { + image = ImageIO.read(new ByteArrayInputStream(imageData)); + } catch (IOException e) { + log.error("Failed to setErrorImage with payload data", e); + image = ERROR_IMAGE; + } + tileState = TileState.TS_ERROR; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + public void loadImage(InputStream input) throws IOException { image = ImageIO.read(input); } @@ -199,10 +220,6 @@ public class Tile { return key; } - public boolean isErrorTile() { - return (ERROR_IMAGE.equals(image)); - } - public TileState getTileState() { return tileState; } @@ -212,8 +229,9 @@ public class Tile { } /** - * Paints the tile-image on the {@link Graphics} g at the position x/y. - * + * Paints the tile-image on the {@link Graphics} g at the position + * x/y. + * * @param g * @param x * x-coordinate in g @@ -221,23 +239,30 @@ public class Tile { * y-coordinate in g */ public void paint(Graphics g, int x, int y) { - if (image == null) - return; - - int tileSize = mapSource.getMapSpace().getTileSize(); - //Google Scale = 2, retina support - g.drawImage(image, x, y, tileSize, tileSize, Color.WHITE, null); - //g.drawImage(image, x, y, Color.WHITE); + paint(g, x, y, Color.WHITE); } public void paintTransparent(Graphics g, int x, int y) { - if (image == null) + paint(g, x, y, null); + } + + public void paint(Graphics g, int x, int y, Color bgColor) { + if (image == null) { return; - + } + int tileSize = mapSource.getMapSpace().getTileSize(); - //Google Scale = 2, retina support - g.drawImage(image, x, y, tileSize, tileSize, null); - //g.drawImage(image, x, y, null); + g.drawImage(image, x, y, tileSize, tileSize, bgColor, null); + if (errorMessage != null) { + g.setColor(Color.BLACK); + int i = 1; + for (String line : errorMessage.split("\n")) { + for (String linepart : line.split("(?<=\\G.{45})")) { + g.drawString(linepart, x + 5, y + (15 * i)); + i++; + } + } + } } @Override @@ -247,8 +272,9 @@ public class Tile { @Override public boolean equals(Object obj) { - if (!(obj instanceof Tile)) + if (!(obj instanceof Tile)) { return false; + } Tile tile = (Tile) obj; return (xtile == tile.xtile) && (ytile == tile.ytile) && (zoom == tile.zoom); } @@ -259,8 +285,8 @@ public class Tile { return -1; } - public static String getTileKey(MapSource source, int xtile, int ytile, int zoom) { - return zoom + "/" + xtile + "/" + ytile + "@" + source.getName(); + public enum TileState { + TS_NEW, TS_LOADING, TS_LOADED, TS_ERROR } } diff --git a/src/main/java/mobac/gui/mapview/TileLoader.java b/mobac/src/main/java/mobac/gui/mapview/TileLoader.java similarity index 63% rename from src/main/java/mobac/gui/mapview/TileLoader.java rename to mobac/src/main/java/mobac/gui/mapview/TileLoader.java index c828209..7b678eb 100644 --- a/src/main/java/mobac/gui/mapview/TileLoader.java +++ b/mobac/src/main/java/mobac/gui/mapview/TileLoader.java @@ -1,26 +1,23 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview; //License: GPL. Copyright 2008 by Jan Peter Stotz -import java.awt.image.BufferedImage; -import java.net.ConnectException; - import mobac.exceptions.DownloadFailedException; import mobac.gui.mapview.Tile.TileState; import mobac.gui.mapview.interfaces.TileLoaderListener; @@ -29,20 +26,24 @@ import mobac.program.interfaces.MapSource; import mobac.program.interfaces.MapSource.LoadMethod; import mobac.program.tilestore.TileStore; import mobac.program.tilestore.TileStoreEntry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Logger; +import javax.net.ssl.SSLHandshakeException; +import java.awt.image.BufferedImage; +import java.io.IOException; /** - * A {@link TileLoaderJobCreator} implementation that loads tiles from OSM via HTTP and saves all loaded files in a - * directory located in the the temporary directory. If a tile is present in this file cache it will not be loaded from - * OSM again. - * + * Loads tiles from OSM via HTTP and saves all loaded files in a directory + * located in the temporary directory. If a tile is present in this file cache + * it will not be loaded from OSM again. + * * @author Jan Peter Stotz * @author r_x */ public class TileLoader { - private static final Logger log = Logger.getLogger(TileLoader.class); + private static final Logger log = LoggerFactory.getLogger(TileLoader.class); protected TileStore tileStore; protected TileLoaderListener listener; @@ -61,9 +62,9 @@ public class TileLoader { final int tilex, tiley, zoom; final MapSource mapSource; + protected TileStoreEntry tileStoreEntry = null; Tile tile; boolean fileTilePainted = false; - protected TileStoreEntry tileStoreEntry = null; public TileAsyncLoadJob(MapSource source, int tilex, int tiley, int zoom) { super(); @@ -74,22 +75,19 @@ public class TileLoader { } public void run() { - MemoryTileCache cache = listener.getTileImageCache(); + final MemoryTileCache cache = listener.getTileImageCache(); synchronized (cache) { tile = cache.getTile(mapSource, tilex, tiley, zoom); - if (tile == null || tile.tileState != TileState.TS_NEW) + if (tile == null || tile.tileState != TileState.TS_NEW) { return; + } tile.setTileState(TileState.TS_LOADING); } - if (loadTileFromStore()) + if (loadTileFromStore()) { return; + } if (fileTilePainted) { - Runnable job = new Runnable() { - - public void run() { - loadOrUpdateTile(); - } - }; + Runnable job = () -> loadOrUpdateTile(); JobDispatcher.getInstance().addJob(job); } else { loadOrUpdateTile(); @@ -108,30 +106,45 @@ public class TileLoader { listener.tileLoadingFinished(tile, false); } return; - } catch (ConnectException e) { - log.warn("Downloading of " + tile + " failed " + e.getMessage()); + } catch (SSLHandshakeException e) { + log.warn("SSL/TLS error prevented download of {}: {}", tile, e.getMessage()); + tile.setErrorImage(); + tile.setErrorMessage("TLS error: " + e.getMessage()); } catch (DownloadFailedException e) { - log.warn("Downloading of " + tile + " failed " + e.getMessage()); + log.warn("Downloading of " + tile + " failed: " + e.getMessage()); + if (e.isTypeImage()) { + tile.setErrorImage(e.getResponseData()); + } else { + tile.setErrorImage(); + tile.setErrorMessage(e.generateResponseErrorText()); + } + } catch (IOException e) { + log.warn("Downloading of {} failed: {}", tile, e.getMessage()); + tile.setErrorImage(); + tile.setErrorMessage(e.getClass().getSimpleName() + "\n" + e.getMessage()); } catch (Exception e) { - log.debug("Downloading of " + tile + " failed", e); + log.debug("Downloading of {} failed", tile, e); + tile.setErrorImage(); + tile.setErrorMessage(e.getClass().getSimpleName() + "\n" + e.getMessage()); } - tile.setErrorImage(); listener.tileLoadingFinished(tile, false); } protected boolean loadTileFromStore() { try { BufferedImage image = mapSource.getTileImage(zoom, tilex, tiley, LoadMethod.CACHE); - if (image == null) + if (image == null) { return false; + } tile.setImage(image); listener.tileLoadingFinished(tile, true); - if (TileDownLoader.isTileExpired(tileStoreEntry)) + if (TileDownLoader.isTileExpired(tileStoreEntry)) { return false; + } fileTilePainted = true; return true; } catch (Exception e) { - log.error("Failed to load tile (z=" + zoom + ",x=" + tilex + ",y=" + tiley + ") from tile store", e); + log.error("Failed to load tile (z={},x={},y={}) from tile store", zoom, tilex, tiley, e); } return false; } diff --git a/src/main/java/mobac/gui/mapview/WgsGrid.java b/mobac/src/main/java/mobac/gui/mapview/WgsGrid.java similarity index 90% rename from src/main/java/mobac/gui/mapview/WgsGrid.java rename to mobac/src/main/java/mobac/gui/mapview/WgsGrid.java index b5f78d3..4fbfc08 100644 --- a/src/main/java/mobac/gui/mapview/WgsGrid.java +++ b/mobac/src/main/java/mobac/gui/mapview/WgsGrid.java @@ -1,21 +1,27 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview; +import mobac.program.interfaces.MapSpace; +import mobac.program.model.Coordinate; +import mobac.program.model.SettingsWgsGrid; +import mobac.utilities.I18nUtils; + +import javax.swing.JComponent; import java.awt.BasicStroke; import java.awt.Color; import java.awt.FontMetrics; @@ -25,67 +31,15 @@ import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Stroke; -import javax.swing.JComponent; - -import mobac.program.interfaces.MapSpace; -import mobac.program.model.Coordinate; -import mobac.program.model.SettingsWgsGrid; -import mobac.utilities.I18nUtils; - public class WgsGrid { - public static enum WgsDensity { - - DEGREES_90(0), DEGREES_45(1), DEGREES_30(2), DEGREES_15(3), DEGREES_10(4), DEGREES_5(5), DEGREES_2(6), DEGREE_1( - 7), MINUTES_30(8), MINUTES_20(9), MINUTES_10(10), MINUTES_5(11), MINUTES_2(12), MINUTE_1(13), SECONDS_30( - 15), SECONDS_20(15), SECONDS_10(16), SECONDS_5(17), SECONDS_2(18), SECOND_1(19); - - public final int iStep, minZoom; - public final boolean compressDegree, compressMinute, displayMinute, displaySecond; - //private final String string; - - private WgsDensity(final int minZoom) { - this.minZoom = minZoom; - String[] split = name().split("_"); - int value = Integer.parseInt(split[1]); - - if (split[0].startsWith("D")) { - iStep = value * Coordinate.DEGREE; - displayMinute = displaySecond = false; - compressDegree = compressMinute = false; - } else if (split[0].startsWith("M")) { - iStep = value * Coordinate.MINUTE; - compressDegree = true/* value <= 15 */; - displayMinute = true; - displaySecond = compressMinute = false; - } else { - iStep = value * Coordinate.SECOND; - compressDegree = displayMinute = displaySecond = true; - compressMinute = true/* value <= 15 */; - } - } - - public String toString() { - String[] split = name().split("_"); - String unitKey = "map_ctrl_wgs_grid_density_"+ split[0].toLowerCase(); - return I18nUtils.localizedStringForKey("map_ctrl_wgs_grid_density_prefix") + " " + split[1] + " " + - I18nUtils.localizedStringForKey(unitKey); - } - } - - public static enum Placement { - BOTTOM_RIGHT, BOTTOM_LEFT, TOP_RIGHT, TOP_LEFT - } - - private static final WgsDensity DENSITIES[] = WgsDensity.values(); + private static final WgsDensity[] DENSITIES = WgsDensity.values(); private static final Stroke BASIC_STROKE = new BasicStroke(1f); private static final int LABEL_OFFSET = 2; - + public final SettingsWgsGrid s; private final StringBuilder stringBuilder = new StringBuilder(16); private final Rectangle viewport = new Rectangle(); - public final SettingsWgsGrid s; private final JComponent c; - private Placement placement = Placement.BOTTOM_RIGHT; private BasicStroke stroke; private int lastDegree, lastMinute; @@ -281,4 +235,47 @@ public class WgsGrid { lastMinute = minute; return stringBuilder.toString(); } + + public enum WgsDensity { + + DEGREES_90(0), DEGREES_45(1), DEGREES_30(2), DEGREES_15(3), DEGREES_10(4), DEGREES_5(5), DEGREES_2(6), DEGREE_1( + 7), MINUTES_30(8), MINUTES_20(9), MINUTES_10(10), MINUTES_5(11), MINUTES_2(12), MINUTE_1( + 13), SECONDS_30(15), SECONDS_20(15), SECONDS_10(16), SECONDS_5(17), SECONDS_2(18), SECOND_1(19); + + public final int iStep, minZoom; + public final boolean compressDegree, compressMinute, displayMinute, displaySecond; + // private final String string; + + WgsDensity(final int minZoom) { + this.minZoom = minZoom; + String[] split = name().split("_"); + int value = Integer.parseInt(split[1]); + + if (split[0].startsWith("D")) { + iStep = value * Coordinate.DEGREE; + displayMinute = displaySecond = false; + compressDegree = compressMinute = false; + } else if (split[0].startsWith("M")) { + iStep = value * Coordinate.MINUTE; + compressDegree = true/* value <= 15 */; + displayMinute = true; + displaySecond = compressMinute = false; + } else { + iStep = value * Coordinate.SECOND; + compressDegree = displayMinute = displaySecond = true; + compressMinute = true/* value <= 15 */; + } + } + + public String toString() { + String[] split = name().split("_"); + String unitKey = "map_ctrl_wgs_grid_density_" + split[0].toLowerCase(); + return I18nUtils.localizedStringForKey("map_ctrl_wgs_grid_density_prefix") + " " + split[1] + " " + + I18nUtils.localizedStringForKey(unitKey); + } + } + + public enum Placement { + BOTTOM_RIGHT, BOTTOM_LEFT, TOP_RIGHT, TOP_LEFT + } } diff --git a/src/main/java/mobac/gui/mapview/controller/AbstractPolygonSelectionMapController.java b/mobac/src/main/java/mobac/gui/mapview/controller/AbstractPolygonSelectionMapController.java similarity index 87% rename from src/main/java/mobac/gui/mapview/controller/AbstractPolygonSelectionMapController.java rename to mobac/src/main/java/mobac/gui/mapview/controller/AbstractPolygonSelectionMapController.java index c54fb8b..54f3dad 100644 --- a/src/main/java/mobac/gui/mapview/controller/AbstractPolygonSelectionMapController.java +++ b/mobac/src/main/java/mobac/gui/mapview/controller/AbstractPolygonSelectionMapController.java @@ -1,29 +1,30 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.controller; -import java.awt.Point; -import java.util.ArrayList; - import mobac.gui.mapview.JMapViewer; import mobac.gui.mapview.PreviewMap; import mobac.gui.mapview.layer.PolygonSelectionLayer; +import java.awt.Point; +import java.util.ArrayList; + /** + * */ public abstract class AbstractPolygonSelectionMapController extends JMapController { @@ -58,7 +59,8 @@ public abstract class AbstractPolygonSelectionMapController extends JMapControll } /** - * @return List of absolute tile coordinate points regarding {@link JMapViewer#MAX_ZOOM} + * @return List of absolute tile coordinate points regarding + * {@link JMapViewer#MAX_ZOOM} */ public ArrayList getPolygonPoints() { return polygonPoints; diff --git a/src/main/java/mobac/gui/mapview/controller/DefaultMapController.java b/mobac/src/main/java/mobac/gui/mapview/controller/DefaultMapController.java similarity index 70% rename from src/main/java/mobac/gui/mapview/controller/DefaultMapController.java rename to mobac/src/main/java/mobac/gui/mapview/controller/DefaultMapController.java index ad962ce..5744d4e 100644 --- a/src/main/java/mobac/gui/mapview/controller/DefaultMapController.java +++ b/mobac/src/main/java/mobac/gui/mapview/controller/DefaultMapController.java @@ -1,23 +1,26 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.controller; //License: GPL. Copyright 2008 by Jan Peter Stotz +import mobac.gui.mapview.PreviewMap; +import mobac.utilities.OSUtilities; + import java.awt.Point; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; @@ -25,43 +28,39 @@ import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; -import mobac.gui.mapview.PreviewMap; -import mobac.utilities.OSUtilities; - /** - * Default map controller which implements map moving by pressing the right mouse button and zooming by double click or - * by mouse wheel. - * + * Default map controller which implements map moving by pressing the right + * mouse button and zooming by double click or by mouse wheel. + * * @author Jan Peter Stotz - * */ -public class DefaultMapController extends JMapController implements MouseListener, MouseMotionListener, - MouseWheelListener { +public class DefaultMapController extends JMapController + implements + MouseListener, + MouseMotionListener, + MouseWheelListener { private static final int MOUSE_BUTTONS_MASK = MouseEvent.BUTTON3_DOWN_MASK | MouseEvent.BUTTON1_DOWN_MASK | MouseEvent.BUTTON2_DOWN_MASK; private static final int MAC_MOUSE_BUTTON3_MASK = MouseEvent.CTRL_DOWN_MASK | MouseEvent.BUTTON1_DOWN_MASK; + public Point lastPoint; + private Point lastDragPoint; + private boolean isMoving = false; + private boolean movementEnabled = true; + private int movementMouseButton = MouseEvent.BUTTON3; + private int movementMouseButtonMask = MouseEvent.BUTTON3_DOWN_MASK; + private boolean wheelZoomEnabled = true; + private boolean doubleClickZoomEnabled = true; public DefaultMapController(PreviewMap map) { super(map, true); } - private Point lastDragPoint; - - private boolean isMoving = false; - - private boolean movementEnabled = true; - - private int movementMouseButton = MouseEvent.BUTTON3; - private int movementMouseButtonMask = MouseEvent.BUTTON3_DOWN_MASK; - - private boolean wheelZoomEnabled = true; - private boolean doubleClickZoomEnabled = true; - public void mouseDragged(MouseEvent e) { - if (!movementEnabled || !isMoving) + if (!movementEnabled || !isMoving) { return; + } // Is only the selected mouse button pressed? if ((e.getModifiersEx() & MOUSE_BUTTONS_MASK) == movementMouseButtonMask) { Point p = e.getPoint(); @@ -75,28 +74,45 @@ public class DefaultMapController extends JMapController implements MouseListene } public void mouseClicked(MouseEvent e) { - if (doubleClickZoomEnabled && e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) - map.zoomIn(e.getPoint()); + if (!map.isMeasuring) { + if (doubleClickZoomEnabled && e.getClickCount() == 2 && e.getButton() == MouseEvent.BUTTON1) { + map.zoomIn(e.getPoint()); + } + } + + // right click delete last inserted segment + if (e.getButton() == 3) { + map.ruler.remove(); + map.repaint(); + } } public void mousePressed(MouseEvent e) { - if (e.getButton() == movementMouseButton || OSUtilities.isPlatformOsx() - && e.getModifiersEx() == MAC_MOUSE_BUTTON3_MASK) { + if (e.getButton() == movementMouseButton + || OSUtilities.IS_PLATFORM_OSX && e.getModifiersEx() == MAC_MOUSE_BUTTON3_MASK) { lastDragPoint = null; isMoving = true; } + + // add ruler point + if (map.isMeasuring && e.getButton() == 1) { + map.ruler.insert(lastPoint); + map.repaint(); + } } public void mouseReleased(MouseEvent e) { - if (e.getButton() == movementMouseButton || OSUtilities.isPlatformOsx() && e.getButton() == MouseEvent.BUTTON1) { + if (e.getButton() == movementMouseButton + || OSUtilities.IS_PLATFORM_OSX && e.getButton() == MouseEvent.BUTTON1) { lastDragPoint = null; isMoving = false; } } public void mouseWheelMoved(MouseWheelEvent e) { - if (wheelZoomEnabled) + if (wheelZoomEnabled) { map.setZoom(map.getZoom() - e.getWheelRotation(), e.getPoint()); + } } public boolean isMovementEnabled() { @@ -105,7 +121,7 @@ public class DefaultMapController extends JMapController implements MouseListene /** * Enables or disables that the map pane can be moved using the mouse. - * + * * @param movementEnabled */ public void setMovementEnabled(boolean movementEnabled) { @@ -123,23 +139,23 @@ public class DefaultMapController extends JMapController implements MouseListene *

  • {@link MouseEvent#BUTTON2} (middle mouse button)
  • *
  • {@link MouseEvent#BUTTON3} (right mouse button)
  • * - * + * * @param movementMouseButton */ public void setMovementMouseButton(int movementMouseButton) { this.movementMouseButton = movementMouseButton; switch (movementMouseButton) { - case MouseEvent.BUTTON1: - movementMouseButtonMask = MouseEvent.BUTTON1_DOWN_MASK; - break; - case MouseEvent.BUTTON2: - movementMouseButtonMask = MouseEvent.BUTTON2_DOWN_MASK; - break; - case MouseEvent.BUTTON3: - movementMouseButtonMask = MouseEvent.BUTTON3_DOWN_MASK; - break; - default: - throw new RuntimeException("Unsupported button"); + case MouseEvent.BUTTON1 : + movementMouseButtonMask = MouseEvent.BUTTON1_DOWN_MASK; + break; + case MouseEvent.BUTTON2 : + movementMouseButtonMask = MouseEvent.BUTTON2_DOWN_MASK; + break; + case MouseEvent.BUTTON3 : + movementMouseButtonMask = MouseEvent.BUTTON3_DOWN_MASK; + break; + default : + throw new RuntimeException("Unsupported button"); } } @@ -166,14 +182,20 @@ public class DefaultMapController extends JMapController implements MouseListene } public void mouseMoved(MouseEvent e) { + Point p = e.getPoint(); + Point tl = map.getTopLeftCoordinate(); + p.x += tl.x; + p.y += tl.y; + lastPoint = p; // Mac OSX simulates with ctrl + mouse 1 the second mouse button hence // no dragging events get fired. - if (!OSUtilities.isPlatformOsx() || !movementEnabled || !isMoving) + if (!OSUtilities.IS_PLATFORM_OSX || !movementEnabled || !isMoving) { return; + } + // Is only the selected mouse button pressed? if (e.getModifiersEx() == MouseEvent.CTRL_DOWN_MASK) { - Point p = e.getPoint(); if (lastDragPoint != null) { int diffx = lastDragPoint.x - p.x; int diffy = lastDragPoint.y - p.y; @@ -181,7 +203,5 @@ public class DefaultMapController extends JMapController implements MouseListene } lastDragPoint = p; } - } - } diff --git a/src/main/java/mobac/gui/mapview/controller/GpxMapController.java b/mobac/src/main/java/mobac/gui/mapview/controller/GpxMapController.java similarity index 87% rename from src/main/java/mobac/gui/mapview/controller/GpxMapController.java rename to mobac/src/main/java/mobac/gui/mapview/controller/GpxMapController.java index 2191fc0..19d1a1a 100644 --- a/src/main/java/mobac/gui/mapview/controller/GpxMapController.java +++ b/mobac/src/main/java/mobac/gui/mapview/controller/GpxMapController.java @@ -1,28 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.controller; -import java.awt.Point; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.math.BigDecimal; - -import javax.swing.JOptionPane; - import mobac.data.gpx.gpx11.Gpx; import mobac.data.gpx.gpx11.WptType; import mobac.gui.actions.GpxEditor; @@ -35,12 +28,18 @@ import mobac.gui.panels.JGpxPanel; import mobac.program.interfaces.MapSpace; import mobac.utilities.I18nUtils; +import javax.swing.JOptionPane; +import java.awt.Point; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.math.BigDecimal; + /** * Allows to create new GPX way-points by clicking on the preview map */ public class GpxMapController extends JMapController implements MouseListener { - private JGpxPanel panel; + private final JGpxPanel panel; private GpxEntry entry; public GpxMapController(PreviewMap map, JGpxPanel panel, boolean enabled) { @@ -55,19 +54,21 @@ public class GpxMapController extends JMapController implements MouseListener { entry = panel.getSelectedEntry(); Gpx gpx = entry.getLayer().getGpx(); Point p = e.getPoint(); - Point tl = ((PreviewMap) map).getTopLeftCoordinate(); + Point tl = map.getTopLeftCoordinate(); p.x += tl.x; p.y += tl.y; MapSpace mapSpace = map.getMapSource().getMapSpace(); int maxPixel = mapSpace.getMaxPixels(map.getZoom()); - if (p.x < 0 || p.x > maxPixel || p.y < 0 || p.y > maxPixel) + if (p.x < 0 || p.x > maxPixel || p.y < 0 || p.y > maxPixel) { return; // outside of world region + } double lon = mapSpace.cXToLon(p.x, map.getZoom()); double lat = mapSpace.cYToLat(p.y, map.getZoom()); String name = JOptionPane.showInputDialog(null, I18nUtils.localizedStringForKey("dlg_gpx_inpu_point_name")); - if (name == null) + if (name == null) { return; - Gpx gpx11 = (Gpx) gpx; + } + Gpx gpx11 = gpx; WptType wpt = new WptType(); wpt.setName(name); wpt.setLat(new BigDecimal(lat)); @@ -108,6 +109,6 @@ public class GpxMapController extends JMapController implements MouseListener { @Override public void disable() { super.disable(); - ((PreviewMap) map).getMapSelectionController().enable(); + map.getMapSelectionController().enable(); } } diff --git a/src/main/java/mobac/gui/mapview/controller/JMapController.java b/mobac/src/main/java/mobac/gui/mapview/controller/JMapController.java similarity index 77% rename from src/main/java/mobac/gui/mapview/controller/JMapController.java rename to mobac/src/main/java/mobac/gui/mapview/controller/JMapController.java index e77d8d1..aeebf2c 100644 --- a/src/main/java/mobac/gui/mapview/controller/JMapController.java +++ b/mobac/src/main/java/mobac/gui/mapview/controller/JMapController.java @@ -1,33 +1,34 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.controller; //License: GPL. Copyright 2008 by Jan Peter Stotz +import mobac.gui.mapview.PreviewMap; + import java.awt.Point; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelListener; -import mobac.gui.mapview.PreviewMap; - /** - * Abstract base class for all mouse controller implementations. For implementing your own controller create a class - * that derives from this one and implements one or more of the following interfaces: + * Abstract base class for all mouse controller implementations. For + * implementing your own controller create a class that derives from this one + * and implements one or more of the following interfaces: *
      *
    • {@link MouseListener}
    • *
    • {@link MouseMotionListener}
    • @@ -45,31 +46,40 @@ public abstract class JMapController { public JMapController(PreviewMap map, boolean enabled) { this(map); - if (enabled) + if (enabled) { enable(); + } } public void enable() { - if (enabled) + if (enabled) { return; - if (this instanceof MouseListener) + } + if (this instanceof MouseListener) { map.addMouseListener((MouseListener) this); - if (this instanceof MouseWheelListener) + } + if (this instanceof MouseWheelListener) { map.addMouseWheelListener((MouseWheelListener) this); - if (this instanceof MouseMotionListener) + } + if (this instanceof MouseMotionListener) { map.addMouseMotionListener((MouseMotionListener) this); + } this.enabled = true; } public void disable() { - if (!enabled) + if (!enabled) { return; - if (this instanceof MouseListener) + } + if (this instanceof MouseListener) { map.removeMouseListener((MouseListener) this); - if (this instanceof MouseWheelListener) + } + if (this instanceof MouseWheelListener) { map.removeMouseWheelListener((MouseWheelListener) this); - if (this instanceof MouseMotionListener) + } + if (this instanceof MouseMotionListener) { map.removeMouseMotionListener((MouseMotionListener) this); + } this.enabled = false; } diff --git a/src/main/java/mobac/gui/mapview/controller/MapKeyboardController.java b/mobac/src/main/java/mobac/gui/mapview/controller/MapKeyboardController.java similarity index 63% rename from src/main/java/mobac/gui/mapview/controller/MapKeyboardController.java rename to mobac/src/main/java/mobac/gui/mapview/controller/MapKeyboardController.java index 73cfea8..a8da4d2 100644 --- a/src/main/java/mobac/gui/mapview/controller/MapKeyboardController.java +++ b/mobac/src/main/java/mobac/gui/mapview/controller/MapKeyboardController.java @@ -1,26 +1,22 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.controller; -import java.awt.event.ActionEvent; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.util.Timer; -import java.util.TimerTask; +import mobac.gui.mapview.PreviewMap; import javax.swing.AbstractAction; import javax.swing.ActionMap; @@ -28,9 +24,11 @@ import javax.swing.ComponentInputMap; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.KeyStroke; - -import mobac.gui.mapview.PreviewMap; - +import java.awt.event.ActionEvent; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.Timer; +import java.util.TimerTask; /** * Implements the GUI logic for the preview map panel that manages the map @@ -38,22 +36,38 @@ import mobac.gui.mapview.PreviewMap; */ public class MapKeyboardController extends JMapController { - /** A Timer for smoothly moving the map area */ + /** + * A Timer for smoothly moving the map area + */ private static final Timer timer = new Timer(true); - - /** Does the moving */ - private MoveTask moveTask = new MoveTask(); - - /** How often to do the moving (milliseconds) */ - private static long timerInterval = 20; - - /** The maximum speed (pixels per timer interval) */ + /** + * The maximum speed (pixels per timer interval) + */ private static final double MAX_SPEED = 20; - - /** The speed increase per timer interval when a cursor button is clicked */ + /** + * The speed increase per timer interval when a cursor button is clicked + */ private static final double ACCELERATION = 0.10; - + private static final String ACTION_MOVE_RIGHT = "MOVE_RIGHT"; + private static final String ACTION_MOVE_LEFT = "MOVE_LEFT"; + private static final String ACTION_MOVE_UP = "MOVE_UP"; + private static final String ACTION_MOVE_DOWN = "MOVE_DOWN"; + private static final String ACTION_STOP_MOVE_HORIZONTALLY = "STOP_MOVE_HORIZONTALLY"; + private static final String ACTION_STOP_MOVE_VERTICALLY = "STOP_MOVE_VERTICALLY"; + private static final String ACTION_ZOOM_IN = "ZOOM_IN"; + private static final String ACTION_ZOOM_OUT = "ZOOM_OUT"; + private static final String ACTION_PREVIOUS_MAP = "PREVIOUS_MAP"; + private static final String ACTION_NEXT_MAP = "NEXT_MAP"; + private static final String ACTION_REFRESH = "REFRESH"; + /** + * How often to do the moving (milliseconds) + */ + private static final long timerInterval = 20; private final InputMap inputMap; + /** + * Does the moving + */ + private MoveTask moveTask = new MoveTask(); public MapKeyboardController(PreviewMap map, boolean enabled) { super(map); @@ -62,60 +76,50 @@ public class MapKeyboardController extends JMapController { ActionMap actionMap = map.getActionMap(); // map moving - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "MOVE_RIGHT"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "MOVE_LEFT"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "MOVE_UP"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "MOVE_DOWN"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "STOP_MOVE_HORIZONTALLY"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "STOP_MOVE_HORIZONTALLY"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "STOP_MOVE_VERTICALLY"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "STOP_MOVE_VERTICALLY"); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), ACTION_MOVE_RIGHT); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), ACTION_MOVE_LEFT); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), ACTION_MOVE_UP); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), ACTION_MOVE_DOWN); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), ACTION_STOP_MOVE_HORIZONTALLY); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), ACTION_STOP_MOVE_HORIZONTALLY); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), ACTION_STOP_MOVE_VERTICALLY); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), ACTION_STOP_MOVE_VERTICALLY); // zooming. To avoid confusion about which modifier key to use, // we just add all keys left of the space bar - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.CTRL_DOWN_MASK, false), - "ZOOM_IN"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.META_DOWN_MASK, false), - "ZOOM_IN"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.ALT_DOWN_MASK, false), - "ZOOM_IN"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.CTRL_DOWN_MASK, false), - "ZOOM_OUT"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.META_DOWN_MASK, false), - "ZOOM_OUT"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.ALT_DOWN_MASK, false), - "ZOOM_OUT"); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.CTRL_DOWN_MASK, false), ACTION_ZOOM_IN); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.META_DOWN_MASK, false), ACTION_ZOOM_IN); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.ALT_DOWN_MASK, false), ACTION_ZOOM_IN); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.CTRL_DOWN_MASK, false), ACTION_ZOOM_OUT); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.META_DOWN_MASK, false), ACTION_ZOOM_OUT); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.ALT_DOWN_MASK, false), ACTION_ZOOM_OUT); // map selection - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.CTRL_DOWN_MASK, false), - "PREVIOUS_MAP"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.META_DOWN_MASK, false), - "PREVIOUS_MAP"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_DOWN_MASK, false), - "PREVIOUS_MAP"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.CTRL_DOWN_MASK, false), - "NEXT_MAP"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.META_DOWN_MASK, false), - "NEXT_MAP"); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_DOWN_MASK, false), - "NEXT_MAP"); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.CTRL_DOWN_MASK, false), ACTION_PREVIOUS_MAP); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.META_DOWN_MASK, false), ACTION_PREVIOUS_MAP); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_DOWN_MASK, false), ACTION_PREVIOUS_MAP); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.CTRL_DOWN_MASK, false), ACTION_NEXT_MAP); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.META_DOWN_MASK, false), ACTION_NEXT_MAP); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_DOWN_MASK, false), ACTION_NEXT_MAP); - inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0, true), "REFRESH"); + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0, true), ACTION_REFRESH); // action mapping - actionMap.put("MOVE_RIGHT", new MoveRightAction()); - actionMap.put("MOVE_LEFT", new MoveLeftAction()); - actionMap.put("MOVE_UP", new MoveUpAction()); - actionMap.put("MOVE_DOWN", new MoveDownAction()); - actionMap.put("STOP_MOVE_HORIZONTALLY", new StopMoveHorizontallyAction()); - actionMap.put("STOP_MOVE_VERTICALLY", new StopMoveVerticallyAction()); - actionMap.put("ZOOM_IN", new ZoomInAction()); - actionMap.put("ZOOM_OUT", new ZoomOutAction()); - actionMap.put("NEXT_MAP", new NextMapAction()); - actionMap.put("PREVIOUS_MAP", new PreviousMapAction()); - actionMap.put("REFRESH", new RefreshAction()); - if (enabled) + actionMap.put(ACTION_MOVE_RIGHT, new MoveRightAction()); + actionMap.put(ACTION_MOVE_LEFT, new MoveLeftAction()); + actionMap.put(ACTION_MOVE_UP, new MoveUpAction()); + actionMap.put(ACTION_MOVE_DOWN, new MoveDownAction()); + actionMap.put(ACTION_STOP_MOVE_HORIZONTALLY, new StopMoveHorizontallyAction()); + actionMap.put(ACTION_STOP_MOVE_VERTICALLY, new StopMoveVerticallyAction()); + actionMap.put(ACTION_ZOOM_IN, new ZoomInAction()); + actionMap.put(ACTION_ZOOM_OUT, new ZoomOutAction()); + actionMap.put(ACTION_NEXT_MAP, new NextMapAction()); + actionMap.put(ACTION_PREVIOUS_MAP, new PreviousMapAction()); + actionMap.put(ACTION_REFRESH, new RefreshAction()); + + if (enabled) { enable(); + } } @Override @@ -176,25 +180,31 @@ public class MapKeyboardController extends JMapController { } } - /** Moves the map depending on which cursor keys are pressed (or not) */ + /** + * Moves the map depending on which cursor keys are pressed (or not) + */ private class MoveTask extends TimerTask { - /** The current x speed (pixels per timer interval) */ - private double speedX = 1; - - /** The current y speed (pixels per timer interval) */ - private double speedY = 1; - - /** The horizontal direction of movement, -1:left, 0:stop, 1:right */ - private int directionX = 0; - - /** The vertical direction of movement, -1:up, 0:stop, 1:down */ - private int directionY = 0; - /** * Indicated if moveTask is currently enabled (periodically * executed via timer) or disabled */ protected boolean scheduled = false; + /** + * The current x speed (pixels per timer interval) + */ + private double speedX = 1; + /** + * The current y speed (pixels per timer interval) + */ + private double speedY = 1; + /** + * The horizontal direction of movement, -1:left, 0:stop, 1:right + */ + private int directionX = 0; + /** + * The vertical direction of movement, -1:up, 0:stop, 1:down + */ + private int directionY = 0; protected void setDirectionX(int directionX) { this.directionX = directionX; @@ -211,9 +221,9 @@ public class MapKeyboardController extends JMapController { if (newMoveTaskState != scheduled) { scheduled = newMoveTaskState; - if (newMoveTaskState) + if (newMoveTaskState) { timer.schedule(this, 0, timerInterval); - else { + } else { // We have to create a new instance because rescheduling a // once canceled TimerTask is not possible moveTask = new MoveTask(); @@ -226,47 +236,56 @@ public class MapKeyboardController extends JMapController { public void run() { // update the x speed switch (directionX) { - case -1: - if (speedX > -1) - speedX = -1; - if (speedX > -1 * MAX_SPEED) - speedX -= ACCELERATION; - break; - case 0: - speedX = 0; - break; - case 1: - if (speedX < 1) - speedX = 1; - if (speedX < MAX_SPEED) - speedX += ACCELERATION; - break; + case -1 : + if (speedX > -1) { + speedX = -1; + } + if (speedX > -1 * MAX_SPEED) { + speedX -= ACCELERATION; + } + break; + case 0 : + speedX = 0; + break; + case 1 : + if (speedX < 1) { + speedX = 1; + } + if (speedX < MAX_SPEED) { + speedX += ACCELERATION; + } + break; } // update the y speed switch (directionY) { - case -1: - if (speedY > -1) - speedY = -1; - if (speedY > -1 * MAX_SPEED) - speedY -= ACCELERATION; - break; - case 0: - speedY = 0; - break; - case 1: - if (speedY < 1) - speedY = 1; - if (speedY < MAX_SPEED) - speedY += ACCELERATION; - break; + case -1 : + if (speedY > -1) { + speedY = -1; + } + if (speedY > -1 * MAX_SPEED) { + speedY -= ACCELERATION; + } + break; + case 0 : + speedY = 0; + break; + case 1 : + if (speedY < 1) { + speedY = 1; + } + if (speedY < MAX_SPEED) { + speedY += ACCELERATION; + } + break; } // move the map int moveX = (int) Math.floor(speedX); int moveY = (int) Math.floor(speedY); - if (moveX != 0 || moveY != 0) + if (moveX != 0 || moveY != 0) { map.moveMap(moveX, moveY); + } } } @@ -290,7 +309,7 @@ public class MapKeyboardController extends JMapController { private static final long serialVersionUID = -1492075614917423363L; public void actionPerformed(ActionEvent e) { - ((PreviewMap) map).selectPreviousMap(); + map.selectPreviousMap(); } } @@ -298,7 +317,7 @@ public class MapKeyboardController extends JMapController { private static final long serialVersionUID = -1491235614917423363L; public void actionPerformed(ActionEvent e) { - ((PreviewMap) map).selectNextMap(); + map.selectNextMap(); } } @@ -307,7 +326,7 @@ public class MapKeyboardController extends JMapController { private static final long serialVersionUID = -7235666079485033823L; public void actionPerformed(ActionEvent e) { - ((PreviewMap) map).refreshMap(); + map.refreshMap(); } } diff --git a/src/main/java/mobac/gui/mapview/controller/PolygonCircleSelectionMapController.java b/mobac/src/main/java/mobac/gui/mapview/controller/PolygonCircleSelectionMapController.java similarity index 88% rename from src/main/java/mobac/gui/mapview/controller/PolygonCircleSelectionMapController.java rename to mobac/src/main/java/mobac/gui/mapview/controller/PolygonCircleSelectionMapController.java index 5246016..83645be 100644 --- a/src/main/java/mobac/gui/mapview/controller/PolygonCircleSelectionMapController.java +++ b/mobac/src/main/java/mobac/gui/mapview/controller/PolygonCircleSelectionMapController.java @@ -1,35 +1,36 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.controller; +import mobac.gui.mapview.PreviewMap; + import java.awt.Point; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; -import mobac.gui.mapview.PreviewMap; - /** - * Implements the GUI logic for the preview map panel that manages the map selection and actions triggered by key - * strokes. - * + * Implements the GUI logic for the preview map panel that manages the map + * selection and actions triggered by key strokes. */ -public class PolygonCircleSelectionMapController extends AbstractPolygonSelectionMapController implements - MouseMotionListener, MouseListener { +public class PolygonCircleSelectionMapController extends AbstractPolygonSelectionMapController + implements + MouseMotionListener, + MouseListener { private static final int POLYGON_POINTS = 16; private static final double ANGLE_PART = Math.PI * 2.0 / POLYGON_POINTS; diff --git a/src/main/java/mobac/gui/mapview/controller/PolygonSelectionMapController.java b/mobac/src/main/java/mobac/gui/mapview/controller/PolygonSelectionMapController.java similarity index 88% rename from src/main/java/mobac/gui/mapview/controller/PolygonSelectionMapController.java rename to mobac/src/main/java/mobac/gui/mapview/controller/PolygonSelectionMapController.java index d1a04d3..d3f367f 100644 --- a/src/main/java/mobac/gui/mapview/controller/PolygonSelectionMapController.java +++ b/mobac/src/main/java/mobac/gui/mapview/controller/PolygonSelectionMapController.java @@ -1,31 +1,30 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.controller; +import mobac.gui.mapview.PreviewMap; + import java.awt.Point; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; -import mobac.gui.mapview.PreviewMap; - /** - * Implements the GUI logic for the preview map panel that manages the map selection and actions triggered by key - * strokes. - * + * Implements the GUI logic for the preview map panel that manages the map + * selection and actions triggered by key strokes. */ public class PolygonSelectionMapController extends AbstractPolygonSelectionMapController implements MouseListener { @@ -42,8 +41,9 @@ public class PolygonSelectionMapController extends AbstractPolygonSelectionMapCo public void mouseReleased(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON1) { - if (finished) + if (finished) { reset(); + } Point mapPoint = map.getTopLeftCoordinate(); mapPoint.x += e.getX(); mapPoint.y += e.getY(); diff --git a/src/main/java/mobac/gui/mapview/controller/RectangleSelectionMapController.java b/mobac/src/main/java/mobac/gui/mapview/controller/RectangleSelectionMapController.java similarity index 88% rename from src/main/java/mobac/gui/mapview/controller/RectangleSelectionMapController.java rename to mobac/src/main/java/mobac/gui/mapview/controller/RectangleSelectionMapController.java index 8ce3773..41fb4f8 100644 --- a/src/main/java/mobac/gui/mapview/controller/RectangleSelectionMapController.java +++ b/mobac/src/main/java/mobac/gui/mapview/controller/RectangleSelectionMapController.java @@ -1,49 +1,48 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.controller; +import mobac.gui.mapview.JMapViewer; +import mobac.gui.mapview.PreviewMap; +import mobac.gui.mapview.layer.RectangleSelectionLayer; + import java.awt.Point; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; -import mobac.gui.mapview.JMapViewer; -import mobac.gui.mapview.PreviewMap; -import mobac.gui.mapview.layer.RectangleSelectionLayer; - /** - * Implements the GUI logic for the preview map panel that manages the map selection and actions triggered by key - * strokes. - * + * Implements the GUI logic for the preview map panel that manages the map + * selection and actions triggered by key strokes. */ public class RectangleSelectionMapController extends JMapController implements MouseMotionListener, MouseListener { + protected RectangleSelectionLayer mapLayer; /** - * start point of selection rectangle in absolute tile coordinated regarding {@link JMapViewer#MAX_ZOOM} + * start point of selection rectangle in absolute tile coordinated regarding + * {@link JMapViewer#MAX_ZOOM} */ private Point iStartSelectionPoint; - /** - * end point of selection rectangle in absolute tile coordinated regarding {@link JMapViewer#MAX_ZOOM} + * end point of selection rectangle in absolute tile coordinated regarding + * {@link JMapViewer#MAX_ZOOM} */ private Point iEndSelectionPoint; - protected RectangleSelectionLayer mapLayer; - public RectangleSelectionMapController(PreviewMap map) { super(map, false); mapLayer = new RectangleSelectionLayer(this); @@ -83,8 +82,8 @@ public class RectangleSelectionMapController extends JMapController implements M } /** - * When dragging the map change the cursor back to it's pre-move cursor. If a double-click occurs center and zoom - * the map on the clicked location. + * When dragging the map change the cursor back to it's pre-move cursor. If a + * double-click occurs center and zoom the map on the clicked location. */ public void mouseReleased(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON1) { diff --git a/src/main/java/mobac/gui/mapview/interfaces/MapEventListener.java b/mobac/src/main/java/mobac/gui/mapview/interfaces/MapEventListener.java similarity index 58% rename from src/main/java/mobac/gui/mapview/interfaces/MapEventListener.java rename to mobac/src/main/java/mobac/gui/mapview/interfaces/MapEventListener.java index eb346ee..8c4b9cb 100644 --- a/src/main/java/mobac/gui/mapview/interfaces/MapEventListener.java +++ b/mobac/src/main/java/mobac/gui/mapview/interfaces/MapEventListener.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.interfaces; @@ -22,22 +22,32 @@ import mobac.program.model.MercatorPixelCoordinate; public interface MapEventListener { - /** the selection changed */ - public void selectionChanged(MercatorPixelCoordinate max, MercatorPixelCoordinate min); + /** + * the selection changed + */ + void selectionChanged(MercatorPixelCoordinate max, MercatorPixelCoordinate min); - /** the zoom changed */ - public void zoomChanged(int newZoomLevel); + /** + * the zoom changed + */ + void zoomChanged(int newZoomLevel); - /** the grid zoom changed */ - public void gridZoomChanged(int newGridZoomLevel); + /** + * the grid zoom changed + */ + void gridZoomChanged(int newGridZoomLevel); - /** select the next map source from the map list */ - public void selectNextMapSource(); + /** + * select the next map source from the map list + */ + void selectNextMapSource(); - /** select the previous map source from the map list */ - public void selectPreviousMapSource(); + /** + * select the previous map source from the map list + */ + void selectPreviousMapSource(); - public void mapSourceChanged(MapSource newMapSource); + void mapSourceChanged(MapSource newMapSource); - public void mapSelectionControllerChanged(JMapController newMapController); + void mapSelectionControllerChanged(JMapController newMapController); } diff --git a/src/main/java/mobac/gui/mapview/interfaces/MapLayer.java b/mobac/src/main/java/mobac/gui/mapview/interfaces/MapLayer.java similarity index 83% rename from src/main/java/mobac/gui/mapview/interfaces/MapLayer.java rename to mobac/src/main/java/mobac/gui/mapview/interfaces/MapLayer.java index 2ca0ee0..0611d85 100644 --- a/src/main/java/mobac/gui/mapview/interfaces/MapLayer.java +++ b/mobac/src/main/java/mobac/gui/mapview/interfaces/MapLayer.java @@ -1,45 +1,44 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.interfaces; -import java.awt.Graphics2D; - import mobac.gui.mapview.JMapViewer; +import java.awt.Graphics2D; + /** * General purpose map layer */ public interface MapLayer { /** - * * @param map * @param g * @param zoom * current zoom level * @param minX * top left x coordinate of the visible map region - * @param minYtop + * @param minY * left y coordinate of the visible map region * @param maxX * bottom right x coordinate of the visible map region * @param maxY * bottom right y coordinate of the visible map region */ - public void paint(JMapViewer map, Graphics2D g, int zoom, int minX, int minY, int maxX, int maxY); + void paint(JMapViewer map, Graphics2D g, int zoom, int minX, int minY, int maxX, int maxY); } diff --git a/src/main/java/mobac/gui/mapview/interfaces/MapTileLayer.java b/mobac/src/main/java/mobac/gui/mapview/interfaces/MapTileLayer.java similarity index 74% rename from src/main/java/mobac/gui/mapview/interfaces/MapTileLayer.java rename to mobac/src/main/java/mobac/gui/mapview/interfaces/MapTileLayer.java index 9cc9d25..747849d 100644 --- a/src/main/java/mobac/gui/mapview/interfaces/MapTileLayer.java +++ b/mobac/src/main/java/mobac/gui/mapview/interfaces/MapTileLayer.java @@ -1,40 +1,40 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.interfaces; -import java.awt.Graphics; - import mobac.program.interfaces.MapSource; +import java.awt.Graphics; + public interface MapTileLayer { - public void startPainting(MapSource mapSource); - + void startPainting(MapSource mapSource); + /** * Paints the tile identified by tilex/tiley/ - * zoom onto the {@link Graphics} g with it's - * upper left corner at gx/gy. The size of each - * tile has to be 256 pixel x 256 pixel. - * + * zoom onto the {@link Graphics} g with it's upper + * left corner at gx/gy. The size of each tile has to + * be 256 pixel x 256 pixel. + * * @param g * @param gx * @param gy * @param tilex * @param tiley */ - public void paintTile(Graphics g, int gx, int gy, int tilex, int tiley, int zoom); + void paintTile(Graphics g, int gx, int gy, int tilex, int tiley, int zoom); } diff --git a/src/main/java/mobac/gui/mapview/interfaces/TileLoaderListener.java b/mobac/src/main/java/mobac/gui/mapview/interfaces/TileLoaderListener.java similarity index 77% rename from src/main/java/mobac/gui/mapview/interfaces/TileLoaderListener.java rename to mobac/src/main/java/mobac/gui/mapview/interfaces/TileLoaderListener.java index 3a87b40..c817e49 100644 --- a/src/main/java/mobac/gui/mapview/interfaces/TileLoaderListener.java +++ b/mobac/src/main/java/mobac/gui/mapview/interfaces/TileLoaderListener.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.interfaces; @@ -24,12 +24,12 @@ import mobac.gui.mapview.Tile; public interface TileLoaderListener { /** - * Will be called if a new {@link Tile} has been loaded successfully. - * Loaded can mean downloaded or loaded from file cache. - * + * Will be called if a new {@link Tile} has been loaded successfully. Loaded can + * mean downloaded or loaded from file cache. + * * @param tile */ - public void tileLoadingFinished(Tile tile, boolean success); + void tileLoadingFinished(Tile tile, boolean success); - public MemoryTileCache getTileImageCache(); + MemoryTileCache getTileImageCache(); } diff --git a/src/main/java/mobac/gui/mapview/layer/DefaultMapTileLayer.java b/mobac/src/main/java/mobac/gui/mapview/layer/DefaultMapTileLayer.java similarity index 80% rename from src/main/java/mobac/gui/mapview/layer/DefaultMapTileLayer.java rename to mobac/src/main/java/mobac/gui/mapview/layer/DefaultMapTileLayer.java index 2b56288..5bddac2 100644 --- a/src/main/java/mobac/gui/mapview/layer/DefaultMapTileLayer.java +++ b/mobac/src/main/java/mobac/gui/mapview/layer/DefaultMapTileLayer.java @@ -1,29 +1,29 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.layer; -import java.awt.Graphics; - import mobac.gui.mapview.JMapViewer; import mobac.gui.mapview.Tile; import mobac.gui.mapview.Tile.TileState; import mobac.gui.mapview.interfaces.MapTileLayer; import mobac.program.interfaces.MapSource; +import java.awt.Graphics; + public class DefaultMapTileLayer implements MapTileLayer { protected JMapViewer mapViewer; @@ -43,34 +43,38 @@ public class DefaultMapTileLayer implements MapTileLayer { public void paintTile(Graphics g, int gx, int gy, int tilex, int tiley, int zoom) { Tile tile = getTile(tilex, tiley, zoom); - if (tile == null) + if (tile == null) { return; + } tile.paint(g, gx, gy); } /** - * retrieves a tile from the cache. If the tile is not present in the cache a load job is added to the working queue - * of {@link JobThread}. - * + * retrieves a tile from the cache. If the tile is not present in the cache a + * load job is added to the working queue. + * * @param tilex * @param tiley * @param zoom - * @return specified tile from the cache or null if the tile was not found in the cache. + * @return specified tile from the cache or null if the tile was + * not found in the cache. */ protected Tile getTile(int tilex, int tiley, int zoom) { int max = (1 << zoom); - if (tilex < 0 || tilex >= max || tiley < 0 || tiley >= max) + if (tilex < 0 || tilex >= max || tiley < 0 || tiley >= max) { return null; + } Tile tile = mapViewer.getTileImageCache().getTile(mapSource, tilex, tiley, zoom); if (tile == null) { tile = new Tile(mapSource, tilex, tiley, zoom); mapViewer.getTileImageCache().addTile(tile); - if (usePlaceHolders) + if (usePlaceHolders) { tile.loadPlaceholderFromCache(mapViewer.getTileImageCache()); + } } if (tile.getTileState() == TileState.TS_NEW) { - mapViewer.getJobDispatcher().addJob( - mapViewer.getTileLoader().createTileLoaderJob(mapSource, tilex, tiley, zoom)); + mapViewer.getJobDispatcher() + .addJob(mapViewer.getTileLoader().createTileLoaderJob(mapSource, tilex, tiley, zoom)); } return tile; diff --git a/src/main/java/mobac/gui/mapview/layer/GpxLayer.java b/mobac/src/main/java/mobac/gui/mapview/layer/GpxLayer.java similarity index 78% rename from src/main/java/mobac/gui/mapview/layer/GpxLayer.java rename to mobac/src/main/java/mobac/gui/mapview/layer/GpxLayer.java index 0909cea..61e77d3 100644 --- a/src/main/java/mobac/gui/mapview/layer/GpxLayer.java +++ b/mobac/src/main/java/mobac/gui/mapview/layer/GpxLayer.java @@ -1,27 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.layer; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Stroke; -import java.io.File; - import mobac.data.gpx.gpx11.Gpx; import mobac.data.gpx.gpx11.RteType; import mobac.data.gpx.gpx11.TrkType; @@ -32,37 +26,43 @@ import mobac.gui.mapview.interfaces.MapLayer; import mobac.gui.panels.JGpxPanel; import mobac.program.interfaces.MapSpace; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Stroke; +import java.io.File; /** - * A {@link MapLayer} displaying the content of a loaded GPX file in a {@link JMapViewer} instance. + * A {@link MapLayer} displaying the content of a loaded GPX file in a + * {@link JMapViewer} instance. */ public class GpxLayer implements MapLayer { - private static int POINT_RADIUS = 4; - private static int POINT_DIAMETER = 2 * POINT_RADIUS; - - private Color wptPointColor = new Color(0, 0, 200); - private Color trkPointColor = Color.RED; - private Color rtePointColor = new Color(0, 200, 0); - - private Stroke outlineStroke = new BasicStroke(1); - - private Stroke lineStroke = new BasicStroke(2.0f); - - // private Logger log = Logger.getLogger(GpxLayer.class); - - /** the associated gpx file handle */ - private File file; - /** the associated gpx object */ + private static final int POINT_RADIUS = 4; + private static final int POINT_DIAMETER = 2 * POINT_RADIUS; + /** + * the associated gpx object + */ private final Gpx gpx; - /** the associated panel that displays the nodes of the gpx file */ + private final Color wptPointColor = new Color(0, 0, 200); + private final Color trkPointColor = Color.RED; + private final Color rtePointColor = new Color(0, 200, 0); + private final Stroke outlineStroke = new BasicStroke(1); + + // private Logger log = LoggerFactory.getLogger(GpxLayer.class); + private final Stroke lineStroke = new BasicStroke(2.0f); + private final boolean showWaypoints = true; + private final boolean showWaypointName = true; + private final boolean showTracks = true; + private final boolean showRoutes = true; + /** + * the associated gpx file handle + */ + private File file; + /** + * the associated panel that displays the nodes of the gpx file + */ private JGpxPanel panel; - - private boolean showWaypoints = true; - private boolean showWaypointName = true; - private boolean showTracks = true; - private boolean showRoutes = true; - private int lastTrackPointX = Integer.MIN_VALUE; private int lastTrackPointY = Integer.MIN_VALUE; @@ -103,11 +103,13 @@ public class GpxLayer implements MapLayer { private boolean paintPoint(final WptType point, Color color, final Graphics2D g, boolean paintPointName, MapSpace mapSpace, int zoom, int minX, int minY, int maxX, int maxY) { int x = mapSpace.cLonToX(point.getLon().doubleValue(), zoom); - if (x < minX || x > maxX) + if (x < minX || x > maxX) { return false; // Point outside of visible region + } int y = mapSpace.cLatToY(point.getLat().doubleValue(), zoom); - if (y < minY || y > maxY) + if (y < minY || y > maxY) { return false; // Point outside of visible region + } x -= minX; y -= minY; g.setColor(color); @@ -115,8 +117,9 @@ public class GpxLayer implements MapLayer { g.setColor(Color.BLACK); g.setStroke(outlineStroke); g.drawOval(x - POINT_RADIUS, y - POINT_RADIUS, POINT_DIAMETER, POINT_DIAMETER); - if (paintPointName && point.getName() != null) + if (paintPointName && point.getName() != null) { g.drawString(point.getName(), x + POINT_RADIUS + 5, y - POINT_RADIUS); + } return true; } @@ -141,32 +144,32 @@ public class GpxLayer implements MapLayer { /** * The associated gpx object - * + * * @return */ public Gpx getGpx() { return gpx; } - public void setPanel(JGpxPanel panel) { - this.panel = panel; - } - public JGpxPanel getPanel() { return panel; } - public void setFile(File file) { - this.file = file; + public void setPanel(JGpxPanel panel) { + this.panel = panel; } /** * The associated gpx file handle - * + * * @return */ public File getFile() { return file; } + public void setFile(File file) { + this.file = file; + } + } diff --git a/src/main/java/mobac/gui/mapview/layer/MapAreaHighlightingLayer.java b/mobac/src/main/java/mobac/gui/mapview/layer/MapAreaHighlightingLayer.java similarity index 92% rename from src/main/java/mobac/gui/mapview/layer/MapAreaHighlightingLayer.java rename to mobac/src/main/java/mobac/gui/mapview/layer/MapAreaHighlightingLayer.java index 4e8e02b..0e6c9a1 100644 --- a/src/main/java/mobac/gui/mapview/layer/MapAreaHighlightingLayer.java +++ b/mobac/src/main/java/mobac/gui/mapview/layer/MapAreaHighlightingLayer.java @@ -1,31 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.layer; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Polygon; -import java.util.Iterator; - -import javax.swing.event.TreeModelEvent; -import javax.swing.event.TreeModelListener; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; - import mobac.gui.MainGUI; import mobac.gui.atlastree.JAtlasTree; import mobac.gui.mapview.JMapViewer; @@ -37,6 +27,15 @@ import mobac.program.interfaces.LayerInterface; import mobac.program.interfaces.MapInterface; import mobac.program.model.MapPolygon; +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Polygon; +import java.util.Iterator; + public class MapAreaHighlightingLayer implements MapLayer, TreeModelListener { private final JAtlasTree tree; @@ -45,19 +44,6 @@ public class MapAreaHighlightingLayer implements MapLayer, TreeModelListener { private AtlasObject object; - public static void removeHighlightingLayers() { - PreviewMap previewMap = MainGUI.getMainGUI().previewMap; - Iterator mapLayers = previewMap.mapLayers.iterator(); - MapLayer ml; - while (mapLayers.hasNext()) { - ml = mapLayers.next(); - if (ml instanceof MapAreaHighlightingLayer) { - mapLayers.remove(); - ((MapAreaHighlightingLayer) ml).unregisterTreeListener(); - } - } - } - public MapAreaHighlightingLayer(AtlasObject atlasObject) { tree = null; treeListener = null; @@ -83,9 +69,26 @@ public class MapAreaHighlightingLayer implements MapLayer, TreeModelListener { tree.getModel().addTreeModelListener(this); } + public static void removeHighlightingLayers(PreviewMap previewMap) { + Iterator mapLayers = previewMap.mapLayers.iterator(); + MapLayer ml; + while (mapLayers.hasNext()) { + ml = mapLayers.next(); + if (ml instanceof MapAreaHighlightingLayer) { + mapLayers.remove(); + ((MapAreaHighlightingLayer) ml).unregisterTreeListener(); + } + } + } + + private static int applyZoomDiff(int pixelCoord, int zoomDiff) { + return (zoomDiff > 0) ? pixelCoord >> zoomDiff : pixelCoord << -zoomDiff; + } + public void paint(JMapViewer mapViewer, Graphics2D g, int zoom, int minX, int minY, int maxX, int maxY) { - if (object == null) + if (object == null) { return; + } if (object instanceof AtlasInterface) { for (LayerInterface layer : (AtlasInterface) object) { for (MapInterface map : layer) { @@ -102,10 +105,11 @@ public class MapAreaHighlightingLayer implements MapLayer, TreeModelListener { } protected void paintMap(MapInterface map, Graphics2D g, int zoom, int minX, int minY, int maxX, int maxY) { - if (map instanceof MapPolygon) + if (map instanceof MapPolygon) { paintMapPolygon((MapPolygon) map, g, zoom, minX, minY, maxX, maxY); - else + } else { paintMapRectangle(map, g, zoom, minX, minY, maxX, maxY); + } } protected void paintMapRectangle(MapInterface map, Graphics2D g, int zoom, int minX, int minY, int maxX, int maxY) { @@ -140,13 +144,10 @@ public class MapAreaHighlightingLayer implements MapLayer, TreeModelListener { g.fillPolygon(px, py, px.length); } - private static int applyZoomDiff(int pixelCoord, int zoomDiff) { - return (zoomDiff > 0) ? pixelCoord >> zoomDiff : pixelCoord << -zoomDiff; - } - protected void unregisterTreeListener() { - if (treeListener == null) + if (treeListener == null) { return; + } try { tree.getModel().removeTreeModelListener(this); tree.removeTreeSelectionListener(treeListener); @@ -156,6 +157,7 @@ public class MapAreaHighlightingLayer implements MapLayer, TreeModelListener { } @Override + @SuppressWarnings("deprecation") protected void finalize() throws Throwable { unregisterTreeListener(); super.finalize(); @@ -185,5 +187,4 @@ public class MapAreaHighlightingLayer implements MapLayer, TreeModelListener { this.object = object; } - } diff --git a/src/main/java/mobac/gui/mapview/layer/MapGridLayer.java b/mobac/src/main/java/mobac/gui/mapview/layer/MapGridLayer.java similarity index 91% rename from src/main/java/mobac/gui/mapview/layer/MapGridLayer.java rename to mobac/src/main/java/mobac/gui/mapview/layer/MapGridLayer.java index aee7a97..a45908e 100644 --- a/src/main/java/mobac/gui/mapview/layer/MapGridLayer.java +++ b/mobac/src/main/java/mobac/gui/mapview/layer/MapGridLayer.java @@ -1,26 +1,25 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.layer; -import java.awt.Graphics; - import mobac.gui.mapview.interfaces.MapTileLayer; import mobac.program.interfaces.MapSource; +import java.awt.Graphics; /** * A simple layer that paints the tile borders. diff --git a/src/main/java/mobac/gui/mapview/layer/OverlayMapTileLayer.java b/mobac/src/main/java/mobac/gui/mapview/layer/OverlayMapTileLayer.java similarity index 81% rename from src/main/java/mobac/gui/mapview/layer/OverlayMapTileLayer.java rename to mobac/src/main/java/mobac/gui/mapview/layer/OverlayMapTileLayer.java index ba14bd9..ea2e352 100644 --- a/src/main/java/mobac/gui/mapview/layer/OverlayMapTileLayer.java +++ b/mobac/src/main/java/mobac/gui/mapview/layer/OverlayMapTileLayer.java @@ -1,29 +1,29 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.layer; -import java.awt.Graphics; - import mobac.gui.mapview.JMapViewer; import mobac.gui.mapview.Tile; import mobac.gui.mapview.Tile.TileState; import mobac.gui.mapview.interfaces.MapTileLayer; import mobac.program.interfaces.MapSource; +import java.awt.Graphics; + public class OverlayMapTileLayer implements MapTileLayer { protected JMapViewer mapViewer; @@ -39,32 +39,35 @@ public class OverlayMapTileLayer implements MapTileLayer { public void paintTile(Graphics g, int gx, int gy, int tilex, int tiley, int zoom) { Tile tile = getTile(tilex, tiley, zoom); - if (tile == null) + if (tile == null) { return; + } tile.paintTransparent(g, gx, gy); } /** - * retrieves a tile from the cache. If the tile is not present in the cache a load job is added to the working queue - * of {@link JobThread}. - * + * retrieves a tile from the cache. If the tile is not present in the cache a + * load job is added to the working queue. + * * @param tilex * @param tiley * @param zoom - * @return specified tile from the cache or null if the tile was not found in the cache. + * @return specified tile from the cache or null if the tile was + * not found in the cache. */ protected Tile getTile(int tilex, int tiley, int zoom) { int max = (1 << zoom); - if (tilex < 0 || tilex >= max || tiley < 0 || tiley >= max) + if (tilex < 0 || tilex >= max || tiley < 0 || tiley >= max) { return null; + } Tile tile = mapViewer.getTileImageCache().getTile(mapSource, tilex, tiley, zoom); if (tile == null) { tile = new Tile(mapSource, tilex, tiley, zoom); mapViewer.getTileImageCache().addTile(tile); } if (tile.getTileState() == TileState.TS_NEW) { - mapViewer.getJobDispatcher().addJob( - mapViewer.getTileLoader().createTileLoaderJob(mapSource, tilex, tiley, zoom)); + mapViewer.getJobDispatcher() + .addJob(mapViewer.getTileLoader().createTileLoaderJob(mapSource, tilex, tiley, zoom)); } return tile; } diff --git a/src/main/java/mobac/gui/mapview/layer/PolygonSelectionLayer.java b/mobac/src/main/java/mobac/gui/mapview/layer/PolygonSelectionLayer.java similarity index 92% rename from src/main/java/mobac/gui/mapview/layer/PolygonSelectionLayer.java rename to mobac/src/main/java/mobac/gui/mapview/layer/PolygonSelectionLayer.java index e71db70..6affa35 100644 --- a/src/main/java/mobac/gui/mapview/layer/PolygonSelectionLayer.java +++ b/mobac/src/main/java/mobac/gui/mapview/layer/PolygonSelectionLayer.java @@ -1,33 +1,33 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.layer; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.geom.AffineTransform; -import java.util.List; - import mobac.gui.mapview.JMapViewer; import mobac.gui.mapview.PreviewMap; import mobac.gui.mapview.controller.AbstractPolygonSelectionMapController; import mobac.gui.mapview.interfaces.MapLayer; import mobac.program.interfaces.MapSpace; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.geom.AffineTransform; +import java.util.List; + /** * Displays a polygon on the map - only for testing purposes */ @@ -44,8 +44,9 @@ public class PolygonSelectionLayer implements MapLayer { g.setColor(Color.RED); Point lastPoint = null; List pointList = mapController.getPolygonPoints(); - if (pointList.size() == 0) + if (pointList.size() == 0) { return; + } AffineTransform at = g.getTransform(); try { g.translate(-minX, -minY); diff --git a/src/main/java/mobac/gui/mapview/layer/RectangleSelectionLayer.java b/mobac/src/main/java/mobac/gui/mapview/layer/RectangleSelectionLayer.java similarity index 92% rename from src/main/java/mobac/gui/mapview/layer/RectangleSelectionLayer.java rename to mobac/src/main/java/mobac/gui/mapview/layer/RectangleSelectionLayer.java index aea3624..f9ccb4f 100644 --- a/src/main/java/mobac/gui/mapview/layer/RectangleSelectionLayer.java +++ b/mobac/src/main/java/mobac/gui/mapview/layer/RectangleSelectionLayer.java @@ -1,32 +1,32 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.layer; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.geom.AffineTransform; - import mobac.gui.mapview.JMapViewer; import mobac.gui.mapview.PreviewMap; import mobac.gui.mapview.controller.RectangleSelectionMapController; import mobac.gui.mapview.interfaces.MapLayer; import mobac.program.interfaces.MapSpace; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.geom.AffineTransform; + /** * Displays a polygon on the map - only for testing purposes */ @@ -43,16 +43,17 @@ public class RectangleSelectionLayer implements MapLayer { g.setColor(Color.BLUE); Point p1 = mapController.getiStartSelectionPoint(); Point p2 = mapController.getiEndSelectionPoint(); - if (p1 == null || p2 == null) + if (p1 == null || p2 == null) { return; + } p1 = mapSpace.changeZoom(p1, PreviewMap.MAX_ZOOM, zoom); p2 = mapSpace.changeZoom(p2, PreviewMap.MAX_ZOOM, zoom); - + int x = Math.min(p1.x, p2.x); int y = Math.min(p1.y, p2.y); int w = Math.abs(p1.x - p2.x); int h = Math.abs(p1.y - p2.y); - + AffineTransform at = g.getTransform(); try { g.translate(-minX, -minY); diff --git a/src/main/java/mobac/gui/mapview/layer/ShapeLayer.java b/mobac/src/main/java/mobac/gui/mapview/layer/ShapeLayer.java similarity index 85% rename from src/main/java/mobac/gui/mapview/layer/ShapeLayer.java rename to mobac/src/main/java/mobac/gui/mapview/layer/ShapeLayer.java index 68c3b0f..8096e28 100644 --- a/src/main/java/mobac/gui/mapview/layer/ShapeLayer.java +++ b/mobac/src/main/java/mobac/gui/mapview/layer/ShapeLayer.java @@ -1,38 +1,37 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.layer; +import mobac.gui.mapview.JMapViewer; +import mobac.gui.mapview.interfaces.MapLayer; + import java.awt.Color; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.AffineTransform; -import mobac.gui.mapview.JMapViewer; -import mobac.gui.mapview.interfaces.MapLayer; - /** * Displays a polygon on the map - only for testing purposes */ public class ShapeLayer implements MapLayer { - private Color color = new Color(0f, 1f, 0f, 0.5f); - + private final Color color = new Color(0f, 1f, 0f, 0.5f); + private final Shape shape; private int calculationZoom; - private Shape shape;; public ShapeLayer(Shape shape, int zoom) { this.shape = shape; @@ -42,10 +41,11 @@ public class ShapeLayer implements MapLayer { AffineTransform af = g.getTransform(); g.translate(-minX, -minY); double scale; - if (zoom < calculationZoom) + if (zoom < calculationZoom) { scale = 1d / (1 << (calculationZoom - zoom)); - else + } else { scale = 1 << (zoom - calculationZoom); + } g.scale(scale, scale); g.setColor(color); g.fill(shape); diff --git a/src/main/java/mobac/gui/mapview/layer/TileStoreCoverageLayer.java b/mobac/src/main/java/mobac/gui/mapview/layer/TileStoreCoverageLayer.java similarity index 91% rename from src/main/java/mobac/gui/mapview/layer/TileStoreCoverageLayer.java rename to mobac/src/main/java/mobac/gui/mapview/layer/TileStoreCoverageLayer.java index 40127d6..944fb57 100644 --- a/src/main/java/mobac/gui/mapview/layer/TileStoreCoverageLayer.java +++ b/mobac/src/main/java/mobac/gui/mapview/layer/TileStoreCoverageLayer.java @@ -1,28 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.mapview.layer; -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.image.BufferedImage; -import java.util.Iterator; - -import javax.swing.JOptionPane; - import mobac.gui.MainGUI; import mobac.gui.dialogs.WorkinprogressDialog; import mobac.gui.mapview.JMapViewer; @@ -35,6 +28,12 @@ import mobac.program.tilestore.berkeleydb.DelayedInterruptThread; import mobac.utilities.GUIExceptionHandler; import mobac.utilities.I18nUtils; +import javax.swing.JOptionPane; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.image.BufferedImage; +import java.util.Iterator; + public class TileStoreCoverageLayer implements MapLayer { private final MapSource mapSource; @@ -45,21 +44,6 @@ public class TileStoreCoverageLayer implements MapLayer { private final Point tileNumMax; private BufferedImage coverageImage = null; - public static void removeCacheCoverageLayers() { - try { - PreviewMap previewMap = MainGUI.getMainGUI().previewMap; - Iterator mapLayers = previewMap.mapLayers.iterator(); - MapLayer ml; - while (mapLayers.hasNext()) { - ml = mapLayers.next(); - if (ml instanceof TileStoreCoverageLayer) { - mapLayers.remove(); - } - } - } catch (Exception e) { - } - } - public TileStoreCoverageLayer(PreviewMap mapViewer, MapSource mapSource, int zoom) { this.mapSource = mapSource; this.zoom = zoom; @@ -79,6 +63,21 @@ public class TileStoreCoverageLayer implements MapLayer { updateCoverageImage(); } + public static void removeCacheCoverageLayers() { + try { + PreviewMap previewMap = MainGUI.getMainGUI().previewMap; + Iterator mapLayers = previewMap.mapLayers.iterator(); + MapLayer ml; + while (mapLayers.hasNext()) { + ml = mapLayers.next(); + if (ml instanceof TileStoreCoverageLayer) { + mapLayers.remove(); + } + } + } catch (Exception e) { + } + } + private void updateCoverageImage() { coverageImage = null; Runnable r = new Runnable() { @@ -86,17 +85,18 @@ public class TileStoreCoverageLayer implements MapLayer { public void run() { try { coverageImage = TileStore.getInstance().getCacheCoverage(mapSource, zoom, tileNumMin, tileNumMax); - if (coverageImage == null) + if (coverageImage == null) { JOptionPane.showMessageDialog(MainGUI.getMainGUI(), - I18nUtils.localizedStringForKey("msg_tile_store_failed_retrieve_coverage"), - I18nUtils.localizedStringForKey("Error"), - JOptionPane.ERROR_MESSAGE); + I18nUtils.localizedStringForKey("msg_tile_store_failed_retrieve_coverage"), + I18nUtils.localizedStringForKey("Error"), JOptionPane.ERROR_MESSAGE); + } } catch (InterruptedException e) { } catch (Exception e) { GUIExceptionHandler.processException(e); } - if (coverageImage == null) + if (coverageImage == null) { removeCacheCoverageLayers(); + } MainGUI.getMainGUI().previewMap.repaint(); } }; @@ -106,8 +106,9 @@ public class TileStoreCoverageLayer implements MapLayer { } public void paint(JMapViewer mapViewer, Graphics2D g, int zoom, int minX, int minY, int maxX, int maxY) { - if (coverageImage == null) + if (coverageImage == null) { return; + } paintCoverage(g, zoom, minX, minY, maxX, maxY); } diff --git a/src/main/java/mobac/gui/panels/JCoordinatesPanel.java b/mobac/src/main/java/mobac/gui/panels/JCoordinatesPanel.java similarity index 90% rename from src/main/java/mobac/gui/panels/JCoordinatesPanel.java rename to mobac/src/main/java/mobac/gui/panels/JCoordinatesPanel.java index 7b9f41a..7603a49 100644 --- a/src/main/java/mobac/gui/panels/JCoordinatesPanel.java +++ b/mobac/src/main/java/mobac/gui/panels/JCoordinatesPanel.java @@ -1,34 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.panels; -import java.awt.BorderLayout; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.text.ParseException; - -import javax.swing.JButton; -import javax.swing.JLabel; -import javax.swing.JLayeredPane; -import javax.swing.JMenuItem; -import javax.swing.JPanel; - import mobac.gui.components.FilledLayeredPane; import mobac.gui.components.JCollapsiblePanel; import mobac.gui.components.JCoordinateField; @@ -41,21 +28,32 @@ import mobac.program.model.MercatorPixelCoordinate; import mobac.utilities.GBC; import mobac.utilities.I18nUtils; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JLayeredPane; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.text.ParseException; + /** - * Encapsulates all interface components and code for the panel that shows the coordinates of the current selection and - * allows the user to enter own coordinates. + * Encapsulates all interface components and code for the panel that shows the + * coordinates of the current selection and allows the user to enter own + * coordinates. */ public class JCoordinatesPanel extends JCollapsiblePanel { + public static final String NAME = "Coordinates";// 用于持久化 private static final long serialVersionUID = 1L; - - public static final String NAME = "Coordinates";//用于持久化 - - private JCoordinateField latMinTextField; - private JCoordinateField latMaxTextField; - private JCoordinateField lonMinTextField; - private JCoordinateField lonMaxTextField; - private JButton applySelectionButton; + private final JCoordinateField latMinTextField; + private final JCoordinateField latMaxTextField; + private final JCoordinateField lonMinTextField; + private final JCoordinateField lonMaxTextField; + private final JButton applySelectionButton; private CoordinateStringFormat csf = CoordinateStringFormat.DEG_ENG; @@ -92,8 +90,9 @@ public class JCoordinatesPanel extends JCollapsiblePanel { formatButton.setMargin(new Insets(0, 5, 0, 0)); formatButton.setBounds(2, 2, 55, 20); formatButtonPanel.add(formatButton); - for (CoordinateStringFormat csf : CoordinateStringFormat.values()) + for (CoordinateStringFormat csf : CoordinateStringFormat.values()) { formatButton.addDropDownItem(new JNumberFormatMenuItem(csf)); + } layeredPane.add(northInnerPanel, Integer.valueOf(0)); layeredPane.setMinimumSize(northInnerPanel.getMinimumSize()); @@ -118,6 +117,10 @@ public class JCoordinatesPanel extends JCollapsiblePanel { contentContainer.add(applySelectionButton, GBC.eol().anchor(GBC.CENTER).insets(0, 5, 0, 0)); } + public CoordinateStringFormat getNumberFormat() { + return csf; + } + public void setNumberFormat(CoordinateStringFormat csf) { this.csf = csf; latMaxTextField.setNumberFormat(csf.getNumberFormatLatitude()); @@ -126,10 +129,6 @@ public class JCoordinatesPanel extends JCollapsiblePanel { lonMinTextField.setNumberFormat(csf.getNumberFormatLongitude()); } - public CoordinateStringFormat getNumberFormat() { - return csf; - } - public void setCoordinates(EastNorthCoordinate max, EastNorthCoordinate min) { latMaxTextField.setCoordinate(max.lat); lonMaxTextField.setCoordinate(max.lon); @@ -153,8 +152,9 @@ public class JCoordinatesPanel extends JCollapsiblePanel { } /** - * Checks if the values for min/max langitude and min/max latitude are interchanged (smaller value in the max field - * and larger value in the min field) and swaps them if necessary. + * Checks if the values for min/max langitude and min/max latitude are + * interchanged (smaller value in the max field and larger value in the min + * field) and swaps them if necessary. */ public void correctMinMax() { try { diff --git a/src/main/java/mobac/gui/panels/JGpxPanel.java b/mobac/src/main/java/mobac/gui/panels/JGpxPanel.java similarity index 91% rename from src/main/java/mobac/gui/panels/JGpxPanel.java rename to mobac/src/main/java/mobac/gui/panels/JGpxPanel.java index 8dcfe9b..8c73910 100644 --- a/src/main/java/mobac/gui/panels/JGpxPanel.java +++ b/mobac/src/main/java/mobac/gui/panels/JGpxPanel.java @@ -1,33 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.panels; -import java.awt.GridBagLayout; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.JButton; -import javax.swing.JScrollPane; -import javax.swing.JTree; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; -import javax.swing.tree.TreePath; -import javax.swing.tree.TreeSelectionModel; - import mobac.data.gpx.gpx11.RteType; import mobac.data.gpx.gpx11.TrkType; import mobac.data.gpx.gpx11.TrksegType; @@ -50,21 +38,31 @@ import mobac.gui.mapview.layer.GpxLayer; import mobac.utilities.GBC; import mobac.utilities.I18nUtils; +import javax.swing.JButton; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreePath; +import javax.swing.tree.TreeSelectionModel; +import java.awt.GridBagLayout; +import java.util.ArrayList; +import java.util.List; + /** - * Allows to load, display, edit and save gpx files using a tree view. TODO warn unsaved changes on exit - * + * Allows to load, display, edit and save gpx files using a tree view. TODO warn + * unsaved changes on exit */ public class JGpxPanel extends JCollapsiblePanel { private static final long serialVersionUID = 1L; - private JTree tree; + private final JTree tree; + private final DefaultTreeModel model; + private final PreviewMap previewMap; private DefaultMutableTreeNode rootNode; - private DefaultTreeModel model; private ArrayList openedFiles; - private PreviewMap previewMap; - public JGpxPanel(PreviewMap previewMap) { super("Gpx", new GridBagLayout()); @@ -109,8 +107,8 @@ public class JGpxPanel extends JCollapsiblePanel { } /** - * adds a layer for a new gpx file on the map and adds its structure to the treeview - * + * adds a layer for a new gpx file on the map and adds its structure to the + * treeview */ public GpxRootEntry addGpxLayer(GpxLayer layer) { layer.setPanel(this); @@ -125,8 +123,9 @@ public class JGpxPanel extends JCollapsiblePanel { addTrks(layer, gpxNode); addWpts(layer, gpxNode); - if (layer.getFile() != null) + if (layer.getFile() != null) { openedFiles.add(layer.getFile().getAbsolutePath()); + } previewMap.mapLayers.add(layer); return gpxEntry; @@ -135,7 +134,6 @@ public class JGpxPanel extends JCollapsiblePanel { /** * @param layer * @param gpxNode - * @param model */ private void addWpts(GpxLayer layer, DefaultMutableTreeNode gpxNode) { List wpts = layer.getGpx().getWpt(); @@ -149,7 +147,6 @@ public class JGpxPanel extends JCollapsiblePanel { /** * @param layer * @param gpxNode - * @param model */ private void addTrks(GpxLayer layer, DefaultMutableTreeNode gpxNode) { // tracks @@ -180,7 +177,7 @@ public class JGpxPanel extends JCollapsiblePanel { /** * adds routes and route points to the tree view - * + * * @param layer * @param gpxNode */ @@ -202,7 +199,7 @@ public class JGpxPanel extends JCollapsiblePanel { /** * Updates the tree view to show the newly added waypoint. - * + * * @param wpt * - new waypoint * @param gpxEntry @@ -216,18 +213,16 @@ public class JGpxPanel extends JCollapsiblePanel { /** * Updates the tree view after removing a waypoint. - * - * @param wpt + * + * @param wptEntry * - deleted waypoint - * @param gpxEntry - * - parent entry of the deleted element in the tree */ public void removeWpt(WptEntry wptEntry) { DefaultMutableTreeNode wptNode = wptEntry.getNode(); model.removeNodeFromParent(wptNode); // update layer (is changing the gpx enough? prolly not - // did remove it already...check wheter its enough + // did remove it already...check whether its enough } public GpxEntry getSelectedEntry() { @@ -252,7 +247,6 @@ public class JGpxPanel extends JCollapsiblePanel { /** * Resets the tree view. Used by GpxClear. - * */ public void resetModel() { rootNode = new DefaultMutableTreeNode(I18nUtils.localizedStringForKey("rp_gpx_default_node_name")); diff --git a/mobac/src/main/java/mobac/gui/panels/JMapSourcesPanel.java b/mobac/src/main/java/mobac/gui/panels/JMapSourcesPanel.java new file mode 100644 index 0000000..561ac20 --- /dev/null +++ b/mobac/src/main/java/mobac/gui/panels/JMapSourcesPanel.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.gui.panels; + +import mobac.gui.components.JCollapsiblePanel; +import mobac.gui.components.JMapSourceTree; +import mobac.program.interfaces.MapSource; +import mobac.utilities.GBC; +import mobac.utilities.I18nUtils; + +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import java.awt.Dimension; +import java.awt.GridBagLayout; + +public class JMapSourcesPanel extends JCollapsiblePanel { + + // initialMapSourceLabel can't be empty to let the mapSourceLabel initialize + // with a proper height + protected static final String initialMapSourceLabel = " "; + private static final long serialVersionUID = 1L; + protected final String plainTitle; + protected JLabel mapSourceLabel; + + public JMapSourcesPanel(JMapSourceTree mapSourceTree) { + super(I18nUtils.localizedStringForKey("lp_map_source_title"), new GridBagLayout()); + plainTitle = getTitle(); + + JScrollPane mapSourceTreeScrollPane = new JScrollPane(mapSourceTree, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, + JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + + mapSourceTreeScrollPane.setPreferredSize(new Dimension(100, 200)); + mapSourceTreeScrollPane.setAutoscrolls(true); + addContent(mapSourceTreeScrollPane, GBC.eol().fill().insets(0, 1, 0, 0)); + } + + @Override + protected void fillTitlePanel() { + super.fillTitlePanel(); + mapSourceLabel = new JLabel(initialMapSourceLabel); + mapSourceLabel.addMouseListener(collapsingMouseListener); + titlePanel.add(mapSourceLabel, GBC.std()); + titlePanel.revalidate(); + } + + public void setMapSourceLabel(MapSource mapSource) { + String mapSourceString = mapSource.toString(); + if (mapSourceString == null) { + mapSourceString = ""; + } + + mapSourceLabel.setText(mapSourceString); + mapSourceLabel.setToolTipText(JMapSourceTree.generateMapSourceTooltip(mapSource)); + mapSourceLabel.setVisible(!mapSourceString.isEmpty()); + } +} diff --git a/src/main/java/mobac/gui/panels/JProfilesPanel.java b/mobac/src/main/java/mobac/gui/panels/JProfilesPanel.java similarity index 86% rename from src/main/java/mobac/gui/panels/JProfilesPanel.java rename to mobac/src/main/java/mobac/gui/panels/JProfilesPanel.java index e99289f..31493d7 100644 --- a/src/main/java/mobac/gui/panels/JProfilesPanel.java +++ b/mobac/src/main/java/mobac/gui/panels/JProfilesPanel.java @@ -1,31 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.panels; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.JButton; -import javax.swing.JOptionPane; -import javax.swing.JPanel; - import mobac.gui.atlastree.JAtlasTree; import mobac.gui.components.JCollapsiblePanel; import mobac.gui.components.JProfilesComboBox; @@ -34,21 +24,31 @@ import mobac.utilities.GBC; import mobac.utilities.I18nUtils; import mobac.utilities.Utilities; +import javax.swing.JButton; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + public class JProfilesPanel extends JCollapsiblePanel { private static final long serialVersionUID = 1L; - private JProfilesComboBox profilesCombo; - private JButton reloadButton; - private JButton deleteButton; - private JButton loadButton; - private JButton saveAsButton; + private final JProfilesComboBox profilesCombo; + private final JButton reloadButton; + private final JButton deleteButton; + private final JButton loadButton; + private final JButton saveAsButton; public JProfilesPanel(JAtlasTree atlasTree) { super(I18nUtils.localizedStringForKey("lp_atlas_profile_title"), new GridBagLayout()); - if (atlasTree == null) + if (atlasTree == null) { throw new NullPointerException(); + } // profiles combo box profilesCombo = new JProfilesComboBox(); @@ -129,33 +129,36 @@ public class JProfilesPanel extends JCollapsiblePanel { } public void actionPerformed(ActionEvent e) { - if (!jAtlasTree.testAtlasContentValid()) + if (!jAtlasTree.testAtlasContentValid()) { return; + } Object selObject = profilesCombo.getEditor().getItem(); String profileName = null; Profile profile = null; if (selObject instanceof Profile) { profile = (Profile) selObject; profileName = profile.getName(); - } else + } else { profileName = (String) selObject; + } if (profileName.length() == 0) { - JOptionPane.showMessageDialog(null, I18nUtils.localizedStringForKey("lp_atlas_profile_msg_ask_name"), - I18nUtils.localizedStringForKey("Error"), - JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(null, I18nUtils.localizedStringForKey("lp_atlas_profile_msg_ask_name"), + I18nUtils.localizedStringForKey("Error"), JOptionPane.ERROR_MESSAGE); return; } profile = new Profile(profileName); if (profile.exists()) { - int response = JOptionPane.showConfirmDialog(null, - String.format(I18nUtils.localizedStringForKey("lp_atlas_profile_msg_overwrite_confirm"), profileName), + int response = JOptionPane.showConfirmDialog(null, + String.format(I18nUtils.localizedStringForKey("lp_atlas_profile_msg_overwrite_confirm"), + profileName), I18nUtils.localizedStringForKey("lp_atlas_profile_msg_overwrite_confirm_title"), JOptionPane.YES_NO_OPTION); - if (response != JOptionPane.YES_OPTION) + if (response != JOptionPane.YES_OPTION) { return; + } } if (jAtlasTree.save(profile)) { diff --git a/src/main/java/mobac/gui/panels/JTileImageParametersPanel.java b/mobac/src/main/java/mobac/gui/panels/JTileImageParametersPanel.java similarity index 80% rename from src/main/java/mobac/gui/panels/JTileImageParametersPanel.java rename to mobac/src/main/java/mobac/gui/panels/JTileImageParametersPanel.java index e634f72..0aff6a5 100644 --- a/src/main/java/mobac/gui/panels/JTileImageParametersPanel.java +++ b/mobac/src/main/java/mobac/gui/panels/JTileImageParametersPanel.java @@ -1,36 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.panels; -import java.awt.Dimension; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Arrays; -import java.util.TreeSet; - -import javax.swing.AbstractListModel; -import javax.swing.ComboBoxModel; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; - import mobac.gui.components.JCollapsiblePanel; import mobac.gui.components.JTileSizeCombo; import mobac.program.annotations.SupportedParameters; @@ -41,22 +26,37 @@ import mobac.program.model.TileImageFormat; import mobac.program.model.TileImageParameters; import mobac.program.model.TileImageParameters.Name; import mobac.program.tiledatawriter.TileImageJpegDataWriter; +import mobac.program.tiledatawriter.TileImageJpegDataWriterBuilder; import mobac.utilities.GBC; import mobac.utilities.I18nUtils; import mobac.utilities.Utilities; +import javax.swing.AbstractListModel; +import javax.swing.ComboBoxModel; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import java.awt.Dimension; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Arrays; +import java.util.TreeSet; + public class JTileImageParametersPanel extends JCollapsiblePanel { private static final long serialVersionUID = 1L; private static boolean JPEG_TESTED = false; - private JCheckBox enableCustomTileProcessingCheckButton; - private JLabel tileSizeWidthLabel; - private JLabel tileSizeHeightLabel; - private JLabel tileImageFormatLabel; - private JTileSizeCombo tileSizeWidth; - private JTileSizeCombo tileSizeHeight; - private JComboBox tileImageFormat; + private final JCheckBox enableCustomTileProcessingCheckButton; + private final JLabel tileSizeWidthLabel; + private final JLabel tileSizeHeightLabel; + private final JLabel tileImageFormatLabel; + private final JTileSizeCombo tileSizeWidth; + private final JTileSizeCombo tileSizeHeight; + private final JComboBox tileImageFormat; private boolean widthEnabled = true; private boolean heightEnabled = true; @@ -70,8 +70,8 @@ public class JTileImageParametersPanel extends JCollapsiblePanel { enableCustomTileProcessingCheckButton = new JCheckBox( I18nUtils.localizedStringForKey("lp_tile_param_recreate_checkbox_title")); enableCustomTileProcessingCheckButton.addActionListener(new EnableCustomTileSizeCheckButtonListener()); - enableCustomTileProcessingCheckButton.setToolTipText(I18nUtils - .localizedStringForKey("lp_tile_param_recreate_checkbox_tips")); + enableCustomTileProcessingCheckButton + .setToolTipText(I18nUtils.localizedStringForKey("lp_tile_param_recreate_checkbox_tips")); tileSizeWidthLabel = new JLabel(I18nUtils.localizedStringForKey("lp_tile_param_width_title")); tileSizeWidth = new JTileSizeCombo(); @@ -125,7 +125,7 @@ public class JTileImageParametersPanel extends JCollapsiblePanel { if (customTileSize) { int width = tileSizeWidth.getValue(); int height = tileSizeHeight.getValue(); - TileImageFormat format = (mobac.program.model.TileImageFormat) tileImageFormat.getSelectedItem(); + TileImageFormat format = (TileImageFormat) tileImageFormat.getSelectedItem(); customTileParameters = new TileImageParameters(width, height, format); } return customTileParameters; @@ -135,8 +135,7 @@ public class JTileImageParametersPanel extends JCollapsiblePanel { Class atlasCreatorClass = newAtlasOutputFormat.getMapCreatorClass(); SupportedParameters params = atlasCreatorClass.getAnnotation(SupportedParameters.class); if (params != null) { - TreeSet paramNames = new TreeSet(Arrays.asList(params - .names())); + TreeSet paramNames = new TreeSet<>(Arrays.asList(params.names())); if (paramNames.contains(Name.format)) { formatPngEnabled = true; formatJpgEnabled = true; @@ -159,8 +158,9 @@ public class JTileImageParametersPanel extends JCollapsiblePanel { public void updateControlsState() { boolean b = false; - if (enableCustomTileProcessingCheckButton.isEnabled()) + if (enableCustomTileProcessingCheckButton.isEnabled()) { b = enableCustomTileProcessingCheckButton.isSelected(); + } tileSizeWidth.setEnabled(b && widthEnabled); tileSizeWidthLabel.setEnabled(b && widthEnabled); tileSizeHeightLabel.setEnabled(b && heightEnabled); @@ -168,12 +168,13 @@ public class JTileImageParametersPanel extends JCollapsiblePanel { boolean formatEnabled = formatJpgEnabled || formatPngEnabled; tileImageFormatLabel.setEnabled(b && formatEnabled); tileImageFormat.setEnabled(b && formatEnabled); - if (formatPngEnabled && !formatJpgEnabled) + if (formatPngEnabled && !formatJpgEnabled) { updateFormatComboModel(TileImageFormat.getPngFormats()); - else if (!formatPngEnabled && formatJpgEnabled) + } else if (!formatPngEnabled && formatJpgEnabled) { updateFormatComboModel(TileImageFormat.getJpgFormats()); - else + } else { updateFormatComboModel(TileImageFormat.values()); + } } private void updateFormatComboModel(TileImageFormat[] values) { @@ -183,15 +184,18 @@ public class JTileImageParametersPanel extends JCollapsiblePanel { public String getValidationErrorMessages() { String errorText = ""; - if (!enableCustomTileProcessingCheckButton.isSelected()) + if (!enableCustomTileProcessingCheckButton.isSelected()) { return errorText; - if (!tileSizeHeight.isValueValid()) + } + if (!tileSizeHeight.isValueValid()) { errorText += String.format(I18nUtils.localizedStringForKey("lp_tile_param_msg_valid_height"), JTileSizeCombo.MIN, JTileSizeCombo.MAX); + } - if (!tileSizeWidth.isValueValid()) + if (!tileSizeWidth.isValueValid()) { errorText += String.format(I18nUtils.localizedStringForKey("lp_tile_param_msg_valid_width"), JTileSizeCombo.MIN, JTileSizeCombo.MAX); + } return errorText; } @@ -204,20 +208,25 @@ public class JTileImageParametersPanel extends JCollapsiblePanel { private class TileImageFormatListener implements ActionListener { public void actionPerformed(ActionEvent event) { - if (!tileImageFormat.isEnabled()) + if (!tileImageFormat.isEnabled()) { return; + } TileImageFormat tif = (TileImageFormat) tileImageFormat.getSelectedItem(); - if (tif == null) + if (tif == null) { return; - if (!JPEG_TESTED && (tif.getDataWriter() instanceof TileImageJpegDataWriter)) { - if (!TileImageJpegDataWriter.performOpenJDKJpegTest()) - JOptionPane.showMessageDialog(null, "The JPEG image format is not supported by OpenJDK.
      " - + "Please select a different tile format.", "Image format not available on OpenJDK", - JOptionPane.ERROR_MESSAGE); + } + if (!JPEG_TESTED && (tif.getDataWriterBuilder() instanceof TileImageJpegDataWriterBuilder)) { + if (!TileImageJpegDataWriter.performOpenJDKJpegTest()) { + JOptionPane.showMessageDialog(null, + "The JPEG image format is not supported by OpenJDK.
      " + + "Please select a different tile format.", + "Image format not available on OpenJDK", JOptionPane.ERROR_MESSAGE); + } JPEG_TESTED = true; } else if (tif == TileImageFormat.PNG4Bit || tif == TileImageFormat.PNG8Bit) { - if (Utilities.testJaiColorQuantizerAvailable()) + if (Utilities.testJaiColorQuantizerAvailable()) { return; + } JOptionPane.showMessageDialog(null, "This image format is requires additional libraries to be installed:
      " + "Java Advanced Image library (jai_core.jar & jai_codec.jar)
      " @@ -229,8 +238,9 @@ public class JTileImageParametersPanel extends JCollapsiblePanel { } } - private class TileFormatComboModel extends AbstractListModel implements - ComboBoxModel { + private static class TileFormatComboModel extends AbstractListModel + implements + ComboBoxModel { TileImageFormat[] values; Object selectedObject = null; @@ -238,8 +248,9 @@ public class JTileImageParametersPanel extends JCollapsiblePanel { public TileFormatComboModel(TileImageFormat[] values) { super(); this.values = values; - if (values.length > 0) + if (values.length > 0) { selectedObject = values[0]; + } } public void changeValues(TileImageFormat[] values) { @@ -251,8 +262,9 @@ public class JTileImageParametersPanel extends JCollapsiblePanel { break; } } - if (!found) + if (!found) { selectedObject = values[0]; + } fireContentsChanged(this, -1, -1); } @@ -264,19 +276,20 @@ public class JTileImageParametersPanel extends JCollapsiblePanel { return values[index]; } + @Override + public Object getSelectedItem() { + return selectedObject; + } + @Override public void setSelectedItem(Object anItem) { - if ((selectedObject != null && !selectedObject.equals(anItem)) || selectedObject == null && anItem != null) { + if ((selectedObject != null && !selectedObject.equals(anItem)) + || selectedObject == null && anItem != null) { selectedObject = anItem; fireContentsChanged(this, -1, -1); } } - @Override - public Object getSelectedItem() { - return selectedObject; - } - } } diff --git a/src/main/java/mobac/gui/panels/JTileStoreCoveragePanel.java b/mobac/src/main/java/mobac/gui/panels/JTileStoreCoveragePanel.java similarity index 84% rename from src/main/java/mobac/gui/panels/JTileStoreCoveragePanel.java rename to mobac/src/main/java/mobac/gui/panels/JTileStoreCoveragePanel.java index 7ba5116..4d5981d 100644 --- a/src/main/java/mobac/gui/panels/JTileStoreCoveragePanel.java +++ b/mobac/src/main/java/mobac/gui/panels/JTileStoreCoveragePanel.java @@ -1,32 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.panels; -import java.awt.FlowLayout; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -import javax.swing.DefaultComboBoxModel; -import javax.swing.JButton; -import javax.swing.JComboBox; -import javax.swing.JLabel; -import javax.swing.JPanel; - import mobac.gui.components.JCollapsiblePanel; import mobac.gui.mapview.PreviewMap; import mobac.gui.mapview.controller.JMapController; @@ -38,16 +27,24 @@ import mobac.program.model.MercatorPixelCoordinate; import mobac.utilities.GBC; import mobac.utilities.I18nUtils; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + public class JTileStoreCoveragePanel extends JCollapsiblePanel implements MapEventListener, ActionListener { - //MP-add + // MP-add private static final long serialVersionUID = 1L; - - private JButton showCoverage; - private JButton hideCoverage; - private JComboBox layerSelector; - private JComboBox zoomCombo; - private PreviewMap mapViewer; + + private final JButton showCoverage; + private final JButton hideCoverage; + private final JComboBox layerSelector; + private final JComboBox zoomCombo; + private final PreviewMap mapViewer; public JTileStoreCoveragePanel(PreviewMap mapViewer) { super(I18nUtils.localizedStringForKey("lp_tile_store_title")); @@ -60,10 +57,10 @@ public class JTileStoreCoveragePanel extends JCollapsiblePanel implements MapEve hideCoverage = new JButton(I18nUtils.localizedStringForKey("lp_tile_store_hide_coverage_btn_title")); hideCoverage.addActionListener(this); hideCoverage.setEnabled(false); - zoomCombo = new JComboBox(); + zoomCombo = new JComboBox<>(); zoomCombo.setToolTipText(I18nUtils.localizedStringForKey("lp_tile_store_zoom_combo_tips")); titlePanel.setToolTipText(I18nUtils.localizedStringForKey("lp_tile_store_title_tips")); - layerSelector = new JComboBox(); + layerSelector = new JComboBox<>(); GBC gbc_eol = GBC.eol().insets(2, 2, 2, 2); GBC gbc_std = GBC.std().insets(2, 2, 2, 2); @@ -86,12 +83,13 @@ public class JTileStoreCoveragePanel extends JCollapsiblePanel implements MapEve return; } Integer zoom = (Integer) zoomCombo.getSelectedItem(); - if (zoom == null) + if (zoom == null) { return; + } TileStoreCoverageLayer.removeCacheCoverageLayers(); mapViewer.repaint(); - TileStoreCoverageLayer tscl = new TileStoreCoverageLayer(mapViewer, - (MapSource) layerSelector.getSelectedItem(), zoom); + TileStoreCoverageLayer tscl = new TileStoreCoverageLayer(mapViewer, (MapSource) layerSelector.getSelectedItem(), + zoom); mapViewer.mapLayers.add(tscl); hideCoverage.setEnabled(true); } @@ -103,15 +101,16 @@ public class JTileStoreCoveragePanel extends JCollapsiblePanel implements MapEve TileStoreCoverageLayer.removeCacheCoverageLayers(); hideCoverage.setEnabled(false); Integer selZoom = (Integer) zoomCombo.getSelectedItem(); - if (selZoom == null) - selZoom = new Integer(8); + if (selZoom == null) { + selZoom = 8; + } int zoomLevels = Math.max(0, newMapSource.getMaxZoom() - newMapSource.getMinZoom() + 1); Integer[] items = new Integer[zoomLevels]; int zoom = newMapSource.getMinZoom(); for (int i = 0; i < items.length; i++) { - items[i] = new Integer(zoom++); + items[i] = zoom++; } - zoomCombo.setModel(new DefaultComboBoxModel(items)); + zoomCombo.setModel(new DefaultComboBoxModel<>(items)); zoomCombo.setMaximumRowCount(10); zoomCombo.setSelectedItem(selZoom); MapSource[] layers; @@ -119,10 +118,10 @@ public class JTileStoreCoveragePanel extends JCollapsiblePanel implements MapEve layers = ((AbstractMultiLayerMapSource) newMapSource).getLayerMapSources(); layerSelector.setEnabled(true); } else { - layers = new MapSource[] { newMapSource }; + layers = new MapSource[]{newMapSource}; layerSelector.setEnabled(false); } - layerSelector.setModel(new DefaultComboBoxModel(layers)); + layerSelector.setModel(new DefaultComboBoxModel<>(layers)); layerSelector.setSelectedIndex(0); } diff --git a/src/main/java/mobac/gui/settings/SettingsGUI.java b/mobac/src/main/java/mobac/gui/settings/SettingsGUI.java similarity index 80% rename from src/main/java/mobac/gui/settings/SettingsGUI.java rename to mobac/src/main/java/mobac/gui/settings/SettingsGUI.java index b9c175a..b8896ad 100644 --- a/src/main/java/mobac/gui/settings/SettingsGUI.java +++ b/mobac/src/main/java/mobac/gui/settings/SettingsGUI.java @@ -1,38 +1,46 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.settings; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.Toolkit; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.File; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Locale; -import java.util.Vector; +import jakarta.xml.bind.JAXBException; +import mobac.StartMOBAC; +import mobac.exceptions.UpdateFailedException; +import mobac.gui.MainGUI; +import mobac.gui.actions.OpenInWebbrowser; +import mobac.gui.components.JDirectoryChooser; +import mobac.gui.components.JMapSizeCombo; +import mobac.gui.components.JTimeSlider; +import mobac.mapsources.DefaultMapSourcesManager; +import mobac.mapsources.MapSourcesManager; +import mobac.mapsources.loader.MapPackManager; +import mobac.program.ProgramInfo; +import mobac.program.interfaces.MapSource; +import mobac.program.model.MapSourcesListModel; +import mobac.program.model.ProxyType; +import mobac.program.model.Settings; +import mobac.program.model.SupportedLocale; +import mobac.program.model.UnitSystem; +import mobac.program.tilestore.TileStore; +import mobac.utilities.GBC; +import mobac.utilities.GUIExceptionHandler; +import mobac.utilities.I18nUtils; +import mobac.utilities.Utilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.swing.AbstractAction; import javax.swing.Action; @@ -64,100 +72,40 @@ import javax.swing.border.EtchedBorder; import javax.swing.border.TitledBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import javax.xml.bind.JAXBException; - -import mobac.StartMOBAC; -import mobac.exceptions.UpdateFailedException; -import mobac.gui.MainGUI; -import mobac.gui.actions.OpenInWebbrowser; -import mobac.gui.components.JDirectoryChooser; -import mobac.gui.components.JMapSizeCombo; -import mobac.gui.components.JTimeSlider; -import mobac.mapsources.DefaultMapSourcesManager; -import mobac.mapsources.MapSourcesManager; -import mobac.mapsources.loader.MapPackManager; -import mobac.program.Logging; -import mobac.program.ProgramInfo; -import mobac.program.interfaces.MapSource; -import mobac.program.model.MapSourcesListModel; -import mobac.program.model.ProxyType; -import mobac.program.model.Settings; -import mobac.program.model.UnitSystem; -import mobac.program.tilestore.TileStore; -import mobac.utilities.GBC; -import mobac.utilities.GUIExceptionHandler; -import mobac.utilities.I18nUtils; -import mobac.utilities.Utilities; - -import org.apache.log4j.Level; -import org.apache.log4j.Logger; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.io.File; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Locale; +import java.util.Vector; public class SettingsGUI extends JDialog { private static final long serialVersionUID = -5227934684609357198L; - public static Logger log = Logger.getLogger(SettingsGUI.class); + private static final Logger LOG = LoggerFactory.getLogger(SettingsGUI.class); - private static final Integer[] THREADCOUNT_LIST = { 1, 2, 4, 6 }; + private static final Integer[] THREADCOUNT_LIST = {1, 2, 4, 6}; private static final long MBIT1 = 1000000 / 8; - - private enum Bandwidth { - UNLIMITED(I18nUtils.localizedStringForKey("set_net_bandwidth_unlimited"), 0), // - MBit1("1 MBit", MBIT1), // - MBit5("5 MBit", MBIT1 * 5), // - MBit10("10 MBit", MBIT1 * 10), // - MBit15("15 MBit", MBIT1 * 15), // - MBit20("20 MBit", MBIT1 * 20); - - public final long limit; - public final String description; - - private Bandwidth(String description, long limit) { - this.description = description; - this.limit = limit; - } - - @Override - public String toString() { - return description; - } - }; - - private enum SupportLocale { - SupportLocaleEn(new Locale("en"), "English"), // default - SupportLocaleFrFR(new Locale("fr", "FR"), "Français"), // French - SupportLocaleJaJP(new Locale("ja", "JP"), "日本語"), // Japanese - SupportLocaleZhCN(new Locale("zh", "CN"), "简体中文"), // Chinese (simplified) - SupportLocaleZhTW(new Locale("zh", "TW"), "繁體中文"); // Chinese (Taiwan) - - private final Locale locale; - private final String displayName; - - private SupportLocale(Locale locale, String displayName) { - this.locale = locale; - this.displayName = displayName; - } - - public static SupportLocale localeOf(String lang, String contry) { - for (SupportLocale l : SupportLocale.values()) { - if (l.locale.getLanguage().equals(lang) && l.locale.getCountry().equals(contry)) { - return l; - } - } - return SupportLocaleEn; - } - - @Override - public String toString() { - return displayName; - } - }; - private final Settings settings = Settings.getInstance(); - private JComboBox unitSystem; + private final SettingsGUIPaper paperAtlas; - private JComboBox languageCombo; + private final SettingsGUIWgsGrid display; + private JComboBox unitSystem; + + private JComboBox languageCombo; private JButton mapSourcesOnlineUpdate; private JTextField osmHikingTicket; @@ -174,10 +122,10 @@ public class SettingsGUI extends JDialog { private JTextField atlasOutputDirectory; - private JComboBox threadCount; - private JComboBox bandwidth; + private JComboBox threadCount; + private JComboBox bandwidth; - private JComboBox proxyType; + private JComboBox proxyType; private JTextField proxyHost; private JTextField proxyPort; @@ -191,27 +139,17 @@ public class SettingsGUI extends JDialog { private JTabbedPane tabbedPane; - private JList enabledMapSources; + private JList enabledMapSources; private MapSourcesListModel enabledMapSourcesModel; - private JList disabledMapSources; + private JList disabledMapSources; private MapSourcesListModel disabledMapSourcesModel; - private final SettingsGUIPaper paperAtlas; - private final SettingsGUIWgsGrid display; - - public static void showSettingsDialog(final JFrame owner) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - new SettingsGUI(owner); - } - }); - } - private SettingsGUI(JFrame owner) { super(owner); + LOG.debug("Preparing settings dialog"); setIconImages(MainGUI.MOBAC_ICONS); GUIExceptionHandler.registerForCurrentThread(); setDefaultCloseOperation(DISPOSE_ON_CLOSE); @@ -226,14 +164,60 @@ public class SettingsGUI extends JDialog { createJButtons(); loadSettings(); addListeners(); + LOG.trace("Settings dialog preparation finished"); + pack(); // don't allow shrinking, but allow enlarging setMinimumSize(getSize()); Dimension dScreen = Toolkit.getDefaultToolkit().getScreenSize(); setLocation((dScreen.width - getWidth()) / 2, (dScreen.height - getHeight()) / 2); + LOG.trace("Make settings dialog visible"); setVisible(true); } + public static void showSettingsDialog(final JFrame owner) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + new SettingsGUI(owner); + } + }); + } + + public static TitledBorder createSectionBorder(String title) { + TitledBorder tb = BorderFactory.createTitledBorder(title); + Border border = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); + Border margin = new EmptyBorder(3, 3, 3, 3); + tb.setBorder(new CompoundBorder(border, margin)); + return tb; + } + + public static void main(String[] args) { + // Logging.configureConsoleLogging(Level.TRACE); + ProgramInfo.initialize(); + DefaultMapSourcesManager.initialize(); + TileStore.initialize(); + StartMOBAC.setLookAndFeel(); + + try { + Settings.load(); + } catch (JAXBException e1) { + e1.printStackTrace(); + } + new SettingsGUI(null); + Runtime.getRuntime().addShutdownHook(new Thread() { + + @Override + public void run() { + try { + Settings.save(); + } catch (JAXBException e) { + e.printStackTrace(); + } + } + + }); + } + private void createJFrame() { setLayout(new BorderLayout()); setTitle(I18nUtils.localizedStringForKey("set_title")); @@ -247,7 +231,7 @@ public class SettingsGUI extends JDialog { try { addMapSourceSettingsPanel(); } catch (URISyntaxException e) { - log.error("", e); + LOG.error("", e); } addMapSourceManagerPanel(); addTileUpdatePanel(); @@ -273,6 +257,7 @@ public class SettingsGUI extends JDialog { } private void addDisplaySettingsPanel() { + LOG.trace("addDisplaySettingsPanel"); JPanel tab = createNewTab(I18nUtils.localizedStringForKey("set_display_title")); tab.setLayout(new GridBagLayout()); @@ -283,12 +268,12 @@ public class SettingsGUI extends JDialog { // Language Panel JPanel languagePanel = new JPanel(new GridBagLayout()); languagePanel.setBorder(createSectionBorder(I18nUtils.localizedStringForKey("set_display_language"))); - languageCombo = new JComboBox(SupportLocale.values()); + languageCombo = new JComboBox<>(SupportedLocale.values()); languageCombo.setToolTipText(I18nUtils.localizedStringForKey("set_display_language_choose_tips")); languageCombo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - Locale locale = ((SupportLocale) languageCombo.getSelectedItem()).locale; + Locale locale = ((SupportedLocale) languageCombo.getSelectedItem()).getLocale(); String currentLocaleStr = "" + settings.localeLanguage + settings.localeCountry; String LocaleStr = "" + locale.getLanguage() + locale.getCountry(); if (!currentLocaleStr.equals(LocaleStr) && isVisible()) { @@ -299,15 +284,15 @@ public class SettingsGUI extends JDialog { I18nUtils.localizedStringForKey("set_display_language_restart_desc"), I18nUtils.localizedStringForKey("set_display_language_msg_title"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); - I18nUtils.updateLocalizedStringFormSettings(); + I18nUtils.updateLocalizedStringFromSettings(); if (result == JOptionPane.YES_OPTION) { applySettings(); try { final String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; - final File currentJar = new File(SettingsGUI.class.getProtectionDomain().getCodeSource() - .getLocation().toURI()); + final File currentJar = new File( + SettingsGUI.class.getProtectionDomain().getCodeSource().getLocation().toURI()); /* is it a jar file? */ if (currentJar.getName().endsWith(".jar")) { @@ -326,7 +311,7 @@ public class SettingsGUI extends JDialog { } command.add(currentJar.getPath()); - log.debug("restarting MOBAC using the following command: \n\t" + LOG.debug("restarting MOBAC using the following command: \n\t" + Arrays.toString(command.toArray())); final ProcessBuilder builder = new ProcessBuilder(command); builder.start(); @@ -345,9 +330,9 @@ public class SettingsGUI extends JDialog { languagePanel.add(Box.createHorizontalGlue(), GBC.eol().fill(GBC.HORIZONTAL)); UnitSystem[] us = UnitSystem.values(); - unitSystem = new JComboBox(us); - unitSystemPanel - .add(new JLabel(I18nUtils.localizedStringForKey("set_display_unit_system_scale_bar")), GBC.std()); + unitSystem = new JComboBox<>(us); + unitSystemPanel.add(new JLabel(I18nUtils.localizedStringForKey("set_display_unit_system_scale_bar")), + GBC.std()); unitSystemPanel.add(unitSystem, GBC.std()); unitSystemPanel.add(Box.createHorizontalGlue(), GBC.eol().fill(GBC.HORIZONTAL)); tab.add(unitSystemPanel, GBC.eol().fill(GBC.HORIZONTAL)); @@ -357,6 +342,7 @@ public class SettingsGUI extends JDialog { } private void addMapSourceSettingsPanel() throws URISyntaxException { + LOG.trace("addMapSourceSettingsPanel"); JPanel tab = createNewTab(I18nUtils.localizedStringForKey("set_mapsrc_config_title")); tab.setLayout(new GridBagLayout()); @@ -377,8 +363,8 @@ public class SettingsGUI extends JDialog { GBC.std()); osmHikingPanel.add(osmHikingTicket, GBC.std().insets(2, 0, 10, 0)); JLabel osmHikingTicketUrl = new JLabel(I18nUtils.localizedStringForKey("set_mapsrc_config_osmhiking_howto")); - osmHikingTicketUrl.addMouseListener(new OpenInWebbrowser(I18nUtils - .localizedStringForKey("set_mapsrc_config_osmhiking_howto_url"))); + osmHikingTicketUrl.addMouseListener( + new OpenInWebbrowser(I18nUtils.localizedStringForKey("set_mapsrc_config_osmhiking_howto_url"))); osmHikingPanel.add(osmHikingTicketUrl, GBC.eol()); tab.add(updatePanel, GBC.eol().fill(GBC.HORIZONTAL)); @@ -387,6 +373,7 @@ public class SettingsGUI extends JDialog { } private void addMapSourceManagerPanel() { + LOG.trace("addMapSourceManagerPanel"); JPanel tab = createNewTab(I18nUtils.localizedStringForKey("set_mapsrc_mgr_title")); tab.setLayout(new GridBagLayout()); @@ -397,22 +384,14 @@ public class SettingsGUI extends JDialog { JPanel rightPanel = new JPanel(new BorderLayout()); rightPanel.setBorder(createSectionBorder(I18nUtils.localizedStringForKey("set_mapsrc_mgr_title_disabled"))); - JButton up = new JButton(Utilities.loadResourceImageIcon("arrow_blue_up.png")); - up.setToolTipText(I18nUtils.localizedStringForKey("set_mapsrc_mgr_move_up_tips")); - JButton down = new JButton(Utilities.loadResourceImageIcon("arrow_blue_down.png")); - down.setToolTipText(I18nUtils.localizedStringForKey("set_mapsrc_mgr_move_down_tips")); JButton toLeft = new JButton(Utilities.loadResourceImageIcon("arrow_blue_left.png")); toLeft.setToolTipText(I18nUtils.localizedStringForKey("set_mapsrc_mgr_move_left_tips")); JButton toRight = new JButton(Utilities.loadResourceImageIcon("arrow_blue_right.png")); toRight.setToolTipText(I18nUtils.localizedStringForKey("set_mapsrc_mgr_move_right_tips")); Insets buttonInsets = new Insets(4, 4, 4, 4); Dimension buttonDimension = new Dimension(40, 40); - up.setPreferredSize(buttonDimension); - down.setPreferredSize(buttonDimension); toLeft.setPreferredSize(buttonDimension); toRight.setPreferredSize(buttonDimension); - up.setMargin(buttonInsets); - down.setMargin(buttonInsets); toLeft.setMargin(buttonInsets); toRight.setMargin(buttonInsets); @@ -437,59 +416,23 @@ public class SettingsGUI extends JDialog { disabledMapSourcesModel.sort(); } }); - up.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - int[] idx = enabledMapSources.getSelectedIndices(); - if (idx.length == 0) - return; - for (int i = 0; i < idx.length; i++) { - int index = idx[i]; - if (index == 0) - return; - if (enabledMapSourcesModel.moveUp(index)) - idx[i]--; - } - enabledMapSources.setSelectedIndices(idx); - enabledMapSources.ensureIndexIsVisible(idx[0]); - } - }); - down.addActionListener(new ActionListener() { - - public void actionPerformed(ActionEvent e) { - int[] idx = enabledMapSources.getSelectedIndices(); - if (idx.length == 0) - return; - for (int i = idx.length - 1; i >= 0; i--) { - int index = idx[i]; - if (index == enabledMapSourcesModel.getSize() - 1) - return; - if (enabledMapSourcesModel.moveDown(index)) - idx[i]++; - } - enabledMapSources.setSelectedIndices(idx); - enabledMapSources.ensureIndexIsVisible(idx[idx.length - 1]); - } - }); GBC buttonGbc = GBC.eol(); centerPanel.add(Box.createVerticalStrut(25), GBC.eol()); centerPanel.add(toLeft, buttonGbc); centerPanel.add(toRight, buttonGbc); - centerPanel.add(up, buttonGbc); - centerPanel.add(down, buttonGbc); centerPanel.add(Box.createVerticalGlue(), GBC.std().fill()); MapSourcesManager msManager = MapSourcesManager.getInstance(); enabledMapSourcesModel = new MapSourcesListModel(msManager.getEnabledOrderedMapSources()); - enabledMapSources = new JList(enabledMapSourcesModel); + enabledMapSources = new JList<>(enabledMapSourcesModel); JScrollPane leftScrollPane = new JScrollPane(enabledMapSources, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); leftPanel.add(leftScrollPane, BorderLayout.CENTER); disabledMapSourcesModel = new MapSourcesListModel(msManager.getDisabledMapSources()); disabledMapSourcesModel.sort(); - disabledMapSources = new JList(disabledMapSourcesModel); + disabledMapSources = new JList<>(disabledMapSourcesModel); JScrollPane rightScrollPane = new JScrollPane(disabledMapSources, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); rightPanel.add(rightScrollPane, BorderLayout.CENTER); @@ -508,6 +451,7 @@ public class SettingsGUI extends JDialog { } private void addTileUpdatePanel() { + LOG.trace("addTileUpdatePanel"); JPanel backGround = createNewTab(I18nUtils.localizedStringForKey("set_tile_update_title")); backGround.setLayout(new GridBagLayout()); @@ -559,13 +503,14 @@ public class SettingsGUI extends JDialog { } private void addMapSizePanel() { + LOG.trace("addMapSizePanel"); JPanel backGround = createNewTab(I18nUtils.localizedStringForKey("set_map_size_title")); backGround.setLayout(new GridBagLayout()); mapSize = new JMapSizeCombo(); mapSize.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - log.trace("Map size: " + mapSize.getValue()); + LOG.trace("Map size: " + mapSize.getValue()); } }); @@ -592,6 +537,7 @@ public class SettingsGUI extends JDialog { } private void addDirectoriesPanel() { + LOG.trace("addDirectoriesPanel"); JPanel backGround = createNewTab(I18nUtils.localizedStringForKey("set_directory_title")); backGround.setLayout(new GridBagLayout()); JPanel atlasOutputDirPanel = new JPanel(new GridBagLayout()); @@ -600,15 +546,17 @@ public class SettingsGUI extends JDialog { atlasOutputDirectory = new JTextField(); atlasOutputDirectory.setToolTipText(String.format(I18nUtils.localizedStringForKey("set_directory_output_tips"), settings.getAtlasOutputDirectory())); - JButton selectAtlasOutputDirectory = new JButton(I18nUtils.localizedStringForKey("set_directory_output_select")); + JButton selectAtlasOutputDirectory = new JButton( + I18nUtils.localizedStringForKey("set_directory_output_select")); selectAtlasOutputDirectory.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JDirectoryChooser dc = new JDirectoryChooser(); dc.setCurrentDirectory(settings.getAtlasOutputDirectory()); - if (dc.showDialog(SettingsGUI.this, - I18nUtils.localizedStringForKey("set_directory_output_select_dlg_title")) != JFileChooser.APPROVE_OPTION) + if (dc.showDialog(SettingsGUI.this, I18nUtils.localizedStringForKey( + "set_directory_output_select_dlg_title")) != JFileChooser.APPROVE_OPTION) { return; + } atlasOutputDirectory.setText(dc.getSelectedFile().getAbsolutePath()); } }); @@ -621,21 +569,23 @@ public class SettingsGUI extends JDialog { } private void addNetworkPanel() { + LOG.trace("addNetworkPanel"); JPanel backGround = createNewTab(I18nUtils.localizedStringForKey("set_net_title")); backGround.setLayout(new GridBagLayout()); GBC gbc_eolh = GBC.eol().fill(GBC.HORIZONTAL); JPanel panel = new JPanel(new GridBagLayout()); panel.setBorder(createSectionBorder(I18nUtils.localizedStringForKey("set_net_connection"))); - threadCount = new JComboBox(THREADCOUNT_LIST); + threadCount = new JComboBox<>(THREADCOUNT_LIST); threadCount.setMaximumRowCount(THREADCOUNT_LIST.length); panel.add(threadCount, GBC.std().insets(5, 5, 5, 5).anchor(GBC.EAST)); - panel.add(new JLabel(I18nUtils.localizedStringForKey("set_net_connection_desc")), GBC.eol() - .fill(GBC.HORIZONTAL)); + panel.add(new JLabel(I18nUtils.localizedStringForKey("set_net_connection_desc")), + GBC.eol().fill(GBC.HORIZONTAL)); - bandwidth = new JComboBox(Bandwidth.values()); + bandwidth = new JComboBox<>(Bandwidth.values()); bandwidth.setMaximumRowCount(bandwidth.getItemCount()); panel.add(bandwidth, GBC.std().insets(5, 5, 5, 5)); - panel.add(new JLabel(I18nUtils.localizedStringForKey("set_net_bandwidth_desc")), GBC.eol().fill(GBC.HORIZONTAL)); + panel.add(new JLabel(I18nUtils.localizedStringForKey("set_net_bandwidth_desc")), + GBC.eol().fill(GBC.HORIZONTAL)); backGround.add(panel, gbc_eolh); @@ -646,7 +596,7 @@ public class SettingsGUI extends JDialog { panel = new JPanel(new GridBagLayout()); panel.setBorder(createSectionBorder(I18nUtils.localizedStringForKey("set_net_proxy"))); final JLabel proxyTypeLabel = new JLabel(I18nUtils.localizedStringForKey("set_net_proxy_settings")); - proxyType = new JComboBox(ProxyType.values()); + proxyType = new JComboBox<>(ProxyType.values()); proxyType.setSelectedItem(settings.getProxyType()); final JLabel proxyHostLabel = new JLabel(I18nUtils.localizedStringForKey("set_net_proxy_host")); @@ -708,6 +658,7 @@ public class SettingsGUI extends JDialog { } public void createJButtons() { + LOG.trace("createJButtons"); JPanel buttonPanel = new JPanel(new GridBagLayout()); okButton = new JButton(I18nUtils.localizedStringForKey("OK")); cancelButton = new JButton(I18nUtils.localizedStringForKey("Cancel")); @@ -719,13 +670,14 @@ public class SettingsGUI extends JDialog { } private void loadSettings() { + LOG.trace("loadSettings()"); Settings s = settings; unitSystem.setSelectedItem(s.unitSystem); tileStoreTab.tileStoreEnabled.setSelected(s.tileStoreEnabled); // language - languageCombo.setSelectedItem(SupportLocale.localeOf(s.localeLanguage, s.localeCountry)); + languageCombo.setSelectedItem(SupportedLocale.localeOf(s.localeLanguage, s.localeCountry)); mapSize.setValue(s.maxMapSize); mapOverlapTiles.setValue(s.mapOverlapTiles); @@ -742,10 +694,11 @@ public class SettingsGUI extends JDialog { int index = Arrays.binarySearch(THREADCOUNT_LIST, s.downloadThreadCount); if (index < 0) { - if (s.downloadThreadCount > THREADCOUNT_LIST[THREADCOUNT_LIST.length - 1]) + if (s.downloadThreadCount > THREADCOUNT_LIST[THREADCOUNT_LIST.length - 1]) { index = THREADCOUNT_LIST.length - 1; - else + } else { index = 0; + } } threadCount.setSelectedIndex(index); @@ -762,8 +715,8 @@ public class SettingsGUI extends JDialog { } /** - * Reads the user defined settings from the gui and updates the {@link Settings} values according to the read gui - * settings. + * Reads the user defined settings from the gui and updates the {@link Settings} + * values according to the read gui settings. */ private void applySettings() { Settings s = settings; @@ -776,12 +729,12 @@ public class SettingsGUI extends JDialog { s.maxMapSize = mapSize.getValue(); s.mapOverlapTiles = (Integer) mapOverlapTiles.getValue(); - Locale locale = ((SupportLocale) languageCombo.getSelectedItem()).locale; + Locale locale = ((SupportedLocale) languageCombo.getSelectedItem()).getLocale(); s.localeLanguage = locale.getLanguage(); s.localeCountry = locale.getCountry(); s.setAtlasOutputDirectory(atlasOutputDirectory.getText()); - int threads = ((Integer) threadCount.getSelectedItem()).intValue(); + int threads = (Integer) threadCount.getSelectedItem(); s.downloadThreadCount = threads; s.setBandwidthLimit(((Bandwidth) bandwidth.getSelectedItem()).limit); @@ -811,8 +764,9 @@ public class SettingsGUI extends JDialog { paperAtlas.applySettings(s); display.applySettings(s); - if (MainGUI.getMainGUI() == null) + if (MainGUI.getMainGUI() == null) { return; + } MainGUI.getMainGUI().updateMapSourcesList(); @@ -820,16 +774,18 @@ public class SettingsGUI extends JDialog { try { MainGUI.getMainGUI().checkAndSaveSettings(); } catch (Exception e) { - log.error("Error saving settings to file", e); - JOptionPane.showMessageDialog(null, String.format(I18nUtils.localizedStringForKey("set_error_saving_msg"), - e.getClass().getSimpleName()), I18nUtils.localizedStringForKey("set_error_saving_title"), - JOptionPane.ERROR_MESSAGE); + LOG.error("Error saving settings to file", e); + JOptionPane.showMessageDialog(null, + String.format(I18nUtils.localizedStringForKey("set_error_saving_msg"), + e.getClass().getSimpleName()), + I18nUtils.localizedStringForKey("set_error_saving_title"), JOptionPane.ERROR_MESSAGE); } MainGUI.getMainGUI().previewMap.repaint(); } private void addListeners() { + LOG.trace("addListeners"); addWindowListener(new WindowCloseListener()); @@ -849,9 +805,11 @@ public class SettingsGUI extends JDialog { tabbedPane.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { - if (tabbedPane.getSelectedComponent() == null) + if (tabbedPane.getSelectedComponent() == null) { return; - // First time the tile store tab is selected start updating the tile store information + } + // First time the tile store tab is selected start updating the tile store + // information if (tabbedPane.getSelectedComponent() == tileStoreTab) { // if ("Tile store".equals(tabbedPane.getSelectedComponent().getName())) { tabbedPane.removeChangeListener(this); @@ -872,12 +830,26 @@ public class SettingsGUI extends JDialog { getRootPane().getActionMap().put("ESCAPE", escapeAction); } - public static final TitledBorder createSectionBorder(String title) { - TitledBorder tb = BorderFactory.createTitledBorder(title); - Border border = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); - Border margin = new EmptyBorder(3, 3, 3, 3); - tb.setBorder(new CompoundBorder(border, margin)); - return tb; + private enum Bandwidth { + UNLIMITED(I18nUtils.localizedStringForKey("set_net_bandwidth_unlimited"), 0), // + MBit1("1 MBit", MBIT1), // + MBit5("5 MBit", MBIT1 * 5), // + MBit10("10 MBit", MBIT1 * 10), // + MBit15("15 MBit", MBIT1 * 15), // + MBit20("20 MBit", MBIT1 * 20); + + public final long limit; + public final String description; + + Bandwidth(String description, long limit) { + this.description = description; + this.limit = limit; + } + + @Override + public String toString() { + return description; + } } private class WindowCloseListener extends WindowAdapter { @@ -896,7 +868,8 @@ public class SettingsGUI extends JDialog { public void actionPerformed(ActionEvent event) { // try { // boolean result = MapSourcesUpdater.mapsourcesOnlineUpdate(); - // String msg = (result) ? "Online update successfull" : "No new update avilable"; + // String msg = (result) ? "Online update successfull" : "No new update + // avilable"; // DateFormat df = DateFormat.getDateTimeInstance(); // Date date = MapSourcesUpdater.getMapSourcesDate(System.getProperties()); // msg += "\nCurrent map source date: " + df.format(date); @@ -904,7 +877,8 @@ public class SettingsGUI extends JDialog { // if (result) // MainGUI.getMainGUI().refreshPreviewMap(); // } catch (MapSourcesUpdateException e) { - // JOptionPane.showMessageDialog(SettingsGUI.this, e.getMessage(), "Mapsources online update failed", + // JOptionPane.showMessageDialog(SettingsGUI.this, e.getMessage(), "Mapsources + // online update failed", // JOptionPane.ERROR_MESSAGE); // } MapPackManager mpm; @@ -912,23 +886,23 @@ public class SettingsGUI extends JDialog { mpm = new MapPackManager(Settings.getInstance().getMapSourcesDirectory()); int result = mpm.updateMapPacks(); switch (result) { - case -1: - JOptionPane.showMessageDialog(SettingsGUI.this, - I18nUtils.localizedStringForKey("set_mapsrc_config_online_update_msg_outdate"), - I18nUtils.localizedStringForKey("set_mapsrc_config_online_update_no_update"), - JOptionPane.ERROR_MESSAGE); - break; - case 0: - JOptionPane.showMessageDialog(SettingsGUI.this, - I18nUtils.localizedStringForKey("set_mapsrc_config_online_update_msg_noneed"), - I18nUtils.localizedStringForKey("set_mapsrc_config_online_update_no_update"), - JOptionPane.INFORMATION_MESSAGE); - break; - default: - JOptionPane.showMessageDialog(SettingsGUI.this, String.format( - I18nUtils.localizedStringForKey("set_mapsrc_config_online_update_msg_done"), result), - I18nUtils.localizedStringForKey("set_mapsrc_config_online_update_done"), - JOptionPane.INFORMATION_MESSAGE); + case -1 : + JOptionPane.showMessageDialog(SettingsGUI.this, + I18nUtils.localizedStringForKey("set_mapsrc_config_online_update_msg_outdate"), + I18nUtils.localizedStringForKey("set_mapsrc_config_online_update_no_update"), + JOptionPane.ERROR_MESSAGE); + break; + case 0 : + JOptionPane.showMessageDialog(SettingsGUI.this, + I18nUtils.localizedStringForKey("set_mapsrc_config_online_update_msg_noneed"), + I18nUtils.localizedStringForKey("set_mapsrc_config_online_update_no_update"), + JOptionPane.INFORMATION_MESSAGE); + break; + default : + JOptionPane.showMessageDialog(SettingsGUI.this, String.format( + I18nUtils.localizedStringForKey("set_mapsrc_config_online_update_msg_done"), result), + I18nUtils.localizedStringForKey("set_mapsrc_config_online_update_done"), + JOptionPane.INFORMATION_MESSAGE); } } catch (UpdateFailedException e) { JOptionPane.showMessageDialog(SettingsGUI.this, e.getMessage(), @@ -940,31 +914,4 @@ public class SettingsGUI extends JDialog { } } } - - public static void main(String[] args) { - Logging.configureConsoleLogging(Level.TRACE); - ProgramInfo.initialize(); - DefaultMapSourcesManager.initialize(); - TileStore.initialize(); - StartMOBAC.setLookAndFeel(); - - try { - Settings.load(); - } catch (JAXBException e1) { - e1.printStackTrace(); - } - new SettingsGUI(null); - Runtime.getRuntime().addShutdownHook(new Thread() { - - @Override - public void run() { - try { - Settings.save(); - } catch (JAXBException e) { - e.printStackTrace(); - } - } - - }); - } } diff --git a/src/main/java/mobac/gui/settings/SettingsGUIPaper.java b/mobac/src/main/java/mobac/gui/settings/SettingsGUIPaper.java similarity index 91% rename from src/main/java/mobac/gui/settings/SettingsGUIPaper.java rename to mobac/src/main/java/mobac/gui/settings/SettingsGUIPaper.java index 0ee7411..8fa6b1e 100644 --- a/src/main/java/mobac/gui/settings/SettingsGUIPaper.java +++ b/mobac/src/main/java/mobac/gui/settings/SettingsGUIPaper.java @@ -1,478 +1,476 @@ -/******************************************************************************* - * Copyright (c) MOBAC developers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ******************************************************************************/ -package mobac.gui.settings; - -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.io.File; - -import javax.swing.BorderFactory; -import javax.swing.Box; -import javax.swing.ButtonGroup; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JFileChooser; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JRadioButton; -import javax.swing.JSpinner; -import javax.swing.SpinnerNumberModel; -import javax.swing.border.TitledBorder; -import javax.swing.filechooser.FileFilter; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; - -import mobac.gui.mapview.WgsGrid.WgsDensity; -import mobac.program.model.PaperSize; -import mobac.program.model.PaperSize.Format; -import mobac.program.model.Settings; -import mobac.program.model.SettingsPaperAtlas; -import mobac.program.model.UnitSystem; -import mobac.utilities.GBCTable; -import mobac.utilities.I18nUtils; - -public class SettingsGUIPaper extends JPanel { - private static final long serialVersionUID = -8265562215604604074L; - - private static void setModel(SpinnerNumberModel model, double min, double max, Double step) { - model.setMaximum(max); - model.setMinimum(min); - model.setStepSize(step); - double value = model.getNumber().doubleValue(); - value = Math.max(Math.min(value, max), min); - model.setValue(value); - } - - private static void setEditor(JSpinner jSpinner, String pattern) { - jSpinner.setEditor(new JSpinner.NumberEditor(jSpinner, pattern)); - } - - private static JPanel createSection(TitledBorder border) { - JPanel jPanel = new JPanel(new GridBagLayout()); - jPanel.setBorder(border); - return jPanel; - } - - private final JButton jButtonDefaults = new JButton(); - private final JButton jButtonExport = new JButton(); - private final JButton jButtonImport = new JButton(); - - private final JCheckBox jCheckBoxCompass = new JCheckBox(); - private final JCheckBox jCheckBoxLandscape = new JCheckBox(); - private final JCheckBox jCheckBoxPageNumbers = new JCheckBox("", true); - private final JCheckBox jCheckBoxScaleBar = new JCheckBox(); - private final JCheckBox jCheckBoxWgsGrid = new JCheckBox("", true); - - private final JFileChooser jFileChooser = new JFileChooser(); - - private final TitledBorder titledBorderActions = SettingsGUI.createSectionBorder(""); - private final TitledBorder titledBorderAdditions = SettingsGUI.createSectionBorder(""); - private final TitledBorder titledBorderAdvanced = SettingsGUI.createSectionBorder(""); - private final TitledBorder titledBorderMargins = SettingsGUI.createSectionBorder(""); - private final TitledBorder titledBorderSize = SettingsGUI.createSectionBorder(""); - - private final JPanel jPanelActions = createSection(titledBorderActions), - jPanelAdditions = createSection(titledBorderAdditions), - jPanelAdvanced = createSection(titledBorderAdvanced), jPanelMargins = createSection(titledBorderMargins), - jPanelSize = createSection(titledBorderSize); - - private final JComboBox jComboBoxFormat = new JComboBox(Format.values()); - private final JComboBox jComboBoxWgsDensity = new JComboBox(WgsDensity.values()); - - private final JRadioButton jRadioButtonCustom = new JRadioButton("", true); - private final JRadioButton jRadioButtonDefault = new JRadioButton("", true); - private final JRadioButton jRadioButtonSelection = new JRadioButton("", true); - - private final SpinnerNumberModel modelCompression = new SpinnerNumberModel(SettingsPaperAtlas.COMPRESSION_DEFAULT, - SettingsPaperAtlas.COMPRESSION_MIN, SettingsPaperAtlas.COMPRESSION_MAX, 1); - - private final SpinnerNumberModel modelCrop = new SpinnerNumberModel(SettingsPaperAtlas.CROP_DEFAULT, - SettingsPaperAtlas.CROP_MIN, SettingsPaperAtlas.CROP_MAX, 1), modelDpi = new SpinnerNumberModel( - SettingsPaperAtlas.DPI_DEFAULT, SettingsPaperAtlas.DPI_MIN, SettingsPaperAtlas.DPI_MAX, 1); - - private final SpinnerNumberModel modelHeight = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); - private final SpinnerNumberModel modelWidth = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); - - private final SpinnerNumberModel modelMarginBottom = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); - private final SpinnerNumberModel modelMarginLeft = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); - private final SpinnerNumberModel modelMarginRight = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); - private final SpinnerNumberModel modelMarginTop = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); - - private final SpinnerNumberModel modelOverlap = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); - - private final JSpinner jSpinnerDpi = new JSpinner(modelDpi), jSpinnerWidth = new JSpinner(modelWidth), - jSpinnerHeight = new JSpinner(modelHeight), jSpinnerMarginTop = new JSpinner(modelMarginTop), - jSpinnerMarginLeft = new JSpinner(modelMarginLeft), jSpinnerMarginBottom = new JSpinner(modelMarginBottom), - jSpinnerMarginRight = new JSpinner(modelMarginRight), jSpinnerOverlap = new JSpinner(modelOverlap), - jSpinnerCrop = new JSpinner(modelCrop), jSpinnerCompression = new JSpinner(modelCompression); - - private final JLabel jLabelCompression = new JLabel(), jLabelDpi = new JLabel(), jLabelWidth = new JLabel(), - jLabelHeight = new JLabel(), jLabelMarginTop = new JLabel(), jLabelMarginLeft = new JLabel(), - jLabelMarginBottom = new JLabel(), jLabelMarginRight = new JLabel(), jLabelOverlap = new JLabel(), - jLabelCrop = new JLabel(); - - private String importError, exportError, errorReason, errorTitle, xmlFileFilter; - - private UnitSystem unitSystem; - - public SettingsGUIPaper() { - super(new GridBagLayout()); - jSpinnerCrop.setEditor(new JSpinner.NumberEditor(jSpinnerCrop, "#0'%'")); - setUnitSystem(UnitSystem.Metric); - i18n(); - jFileChooser.setFileFilter(new FileFilter() { - @Override - public boolean accept(File f) { - return f.isDirectory() || f.getName().endsWith(".xml"); - } - - @Override - public String getDescription() { - return xmlFileFilter; - } - }); - jButtonImport.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - importFromXml(); - } - }); - jButtonExport.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - exportToXml(); - } - }); - jButtonDefaults.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - resetToDefaults(); - } - }); - jComboBoxFormat.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Format format = (Format) jComboBoxFormat.getSelectedItem(); - double width = unitSystem.pointsToUnits(format.width); - double height = unitSystem.pointsToUnits(format.height); - modelWidth.setValue(width); - modelHeight.setValue(height); - } - }); - jCheckBoxWgsGrid.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - boolean enabled = e.getStateChange() != ItemEvent.DESELECTED; - jComboBoxWgsDensity.setEnabled(enabled); - } - }); - jRadioButtonCustom.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - boolean enabled = e.getStateChange() != ItemEvent.DESELECTED; - jLabelWidth.setEnabled(enabled); - jLabelHeight.setEnabled(enabled); - jSpinnerWidth.setEnabled(enabled); - jSpinnerHeight.setEnabled(enabled); - } - }); - jRadioButtonDefault.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - boolean enabled = e.getStateChange() != ItemEvent.DESELECTED; - jComboBoxFormat.setEnabled(enabled); - jCheckBoxLandscape.setEnabled(enabled); - } - }); - - ButtonGroup buttonGroup = new ButtonGroup(); - buttonGroup.add(jRadioButtonSelection); - buttonGroup.add(jRadioButtonDefault); - buttonGroup.add(jRadioButtonCustom); - - GBCTable gbc = new GBCTable(); - - jPanelSize.add(jRadioButtonDefault, gbc.begin()); - jPanelSize.add(jRadioButtonCustom, gbc.incY()); - jPanelSize.add(jRadioButtonSelection, gbc.incY()); - jPanelSize.add(jComboBoxFormat, gbc.incX()); - jPanelSize.add(jLabelWidth, gbc.incY()); - jPanelSize.add(jLabelHeight, gbc.incY()); - jPanelSize.add(jCheckBoxLandscape, gbc.incX()); - jPanelSize.add(jSpinnerWidth, gbc.incY()); - jPanelSize.add(jSpinnerHeight, gbc.incY()); - jPanelSize.add(Box.createGlue(), gbc.incX().gridheight(3).fill()); - - jPanelMargins.add(jLabelMarginTop, gbc.begin()); - jPanelMargins.add(jLabelMarginBottom, gbc.incY()); - jPanelMargins.add(jSpinnerMarginTop, gbc.incX()); - jPanelMargins.add(jSpinnerMarginBottom, gbc.incY()); - jPanelMargins.add(jLabelMarginLeft, gbc.incX()); - jPanelMargins.add(jLabelMarginRight, gbc.incY()); - jPanelMargins.add(jSpinnerMarginLeft, gbc.incX()); - jPanelMargins.add(jSpinnerMarginRight, gbc.incY()); - jPanelMargins.add(Box.createHorizontalGlue(), gbc.incX().fillH()); - - jPanelAdditions.add(jCheckBoxWgsGrid, gbc.begin()); - jPanelAdditions.add(jCheckBoxPageNumbers, gbc.incY().gridwidth(2)); - jPanelAdditions.add(jCheckBoxScaleBar, gbc.incY()); - jPanelAdditions.add(jComboBoxWgsDensity, gbc.incX()); - gbc.incY(); - jPanelAdditions.add(jCheckBoxCompass, gbc.incY()); - jPanelAdditions.add(Box.createHorizontalGlue(), gbc.incX().fillH()); - - jPanelAdvanced.add(jLabelDpi, gbc.begin()); - jPanelAdvanced.add(jLabelCompression, gbc.incY()); - jPanelAdvanced.add(jSpinnerDpi, gbc.incX()); - jPanelAdvanced.add(jSpinnerCompression, gbc.incY()); - jPanelAdvanced.add(jLabelOverlap, gbc.incX()); - jPanelAdvanced.add(jLabelCrop, gbc.incY()); - jPanelAdvanced.add(jSpinnerOverlap, gbc.incX()); - jPanelAdvanced.add(jSpinnerCrop, gbc.incY()); - jPanelAdvanced.add(Box.createHorizontalGlue(), gbc.incX().fillH()); - - jPanelActions.add(jButtonImport, gbc.begin()); - jPanelActions.add(jButtonExport, gbc.incX()); - jPanelActions.add(jButtonDefaults, gbc.incX()); - jPanelActions.add(Box.createHorizontalGlue(), gbc.incX().fillH()); - - gbc = new GBCTable(0); - setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - add(jPanelSize, gbc.begin()); - add(jPanelMargins, gbc.incY()); - add(jPanelAdditions, gbc.incX().fillH()); - add(jPanelAdvanced, gbc.incY().fillH()); - add(jPanelActions, gbc.begin(1, 3).gridwidth(2).fillH()); - add(Box.createGlue(), gbc.incY().gridwidth(2).fill()); - } - - private void importFromXml() { - int state = jFileChooser.showOpenDialog(SettingsGUIPaper.this); - if (state == JFileChooser.APPROVE_OPTION) { - File file = jFileChooser.getSelectedFile(); - JAXBContext context; - try { - context = JAXBContext.newInstance(SettingsPaperAtlas.class); - Unmarshaller um = context.createUnmarshaller(); - SettingsPaperAtlas s = (SettingsPaperAtlas) um.unmarshal(file); - loadSettings(s); - } catch (JAXBException ex) { - String text = importError + file.getName() + "\n" + errorReason + ex.getMessage(); - JOptionPane.showMessageDialog(SettingsGUIPaper.this, text, errorTitle, JOptionPane.ERROR_MESSAGE); - } - } - } - - private void exportToXml() { - int state = jFileChooser.showSaveDialog(SettingsGUIPaper.this); - if (state == JFileChooser.APPROVE_OPTION) { - File file = jFileChooser.getSelectedFile(); - JAXBContext context; - try { - context = JAXBContext.newInstance(SettingsPaperAtlas.class); - Marshaller m = context.createMarshaller(); - SettingsPaperAtlas s = new SettingsPaperAtlas(); - applySettings(s); - m.marshal(s, file); - } catch (JAXBException ex) { - String text = exportError + file.getName() + "\n" + errorReason + ex.getMessage(); - JOptionPane.showMessageDialog(SettingsGUIPaper.this, text, errorTitle, JOptionPane.ERROR_MESSAGE); - } - } - } - - private void resetToDefaults() { - loadSettings(new SettingsPaperAtlas()); - } - - private void i18n() { - setName(I18nUtils.localizedStringForKey("set_paper_title")); - titledBorderActions.setTitle(I18nUtils.localizedStringForKey("set_paper_actions")); - titledBorderAdditions.setTitle(I18nUtils.localizedStringForKey("set_paper_additions")); - titledBorderAdvanced.setTitle(I18nUtils.localizedStringForKey("set_paper_advanced")); - titledBorderMargins.setTitle(I18nUtils.localizedStringForKey("set_paper_margins")); - titledBorderSize.setTitle(I18nUtils.localizedStringForKey("set_paper_size")); - jComboBoxFormat.setToolTipText(I18nUtils.localizedStringForKey("set_paper_size_default_format_tips")); - jComboBoxWgsDensity.setToolTipText(I18nUtils.localizedStringForKey("set_paper_wgs_grid_density_tips")); - jRadioButtonSelection.setText(I18nUtils.localizedStringForKey("set_paper_size_selection")); - jRadioButtonSelection.setToolTipText(I18nUtils.localizedStringForKey("set_paper_size_selection_tips")); - jRadioButtonDefault.setText(I18nUtils.localizedStringForKey("set_paper_size_default")); - jRadioButtonDefault.setToolTipText(I18nUtils.localizedStringForKey("set_paper_size_default_tips")); - jRadioButtonCustom.setText(I18nUtils.localizedStringForKey("set_paper_size_custom")); - jRadioButtonCustom.setToolTipText(I18nUtils.localizedStringForKey("set_paper_size_custom_tips")); - jCheckBoxScaleBar.setText(I18nUtils.localizedStringForKey("set_paper_scale_bar")); - jCheckBoxScaleBar.setToolTipText(I18nUtils.localizedStringForKey("set_paper_scale_tips")); - jCheckBoxCompass.setText(I18nUtils.localizedStringForKey("set_paper_compass")); - jCheckBoxCompass.setToolTipText(I18nUtils.localizedStringForKey("set_paper_compass_tips")); - jCheckBoxLandscape.setText(I18nUtils.localizedStringForKey("set_paper_size_default_landscape")); - jCheckBoxLandscape.setToolTipText(I18nUtils.localizedStringForKey("set_paper_size_default_landscape_tips")); - jCheckBoxWgsGrid.setText(I18nUtils.localizedStringForKey(I18nUtils.localizedStringForKey("set_paper_wgs_grid"))); - jCheckBoxWgsGrid.setToolTipText(I18nUtils.localizedStringForKey("set_paper_wgs_grid_tips")); - jCheckBoxPageNumbers.setText(I18nUtils.localizedStringForKey("set_paper_paper_nubmer")); - jCheckBoxPageNumbers.setToolTipText(I18nUtils.localizedStringForKey("set_paper_paper_nubmer_tips")); - jLabelCompression.setText(I18nUtils.localizedStringForKey("set_paper_advanced_compression")); - String compression = I18nUtils.localizedStringForKey("set_paper_advanced_compression_tips"); - jLabelCompression.setToolTipText(compression); - jSpinnerCompression.setToolTipText(compression); - jLabelDpi.setText(I18nUtils.localizedStringForKey("set_paper_advanced_dpi")); - String dpi = I18nUtils.localizedStringForKey("set_paper_advanced_dpi_tips"); - jLabelDpi.setToolTipText(dpi); - jSpinnerDpi.setToolTipText(dpi); - jLabelWidth.setText(I18nUtils.localizedStringForKey("set_paper_size_custom_width")); - String width = I18nUtils.localizedStringForKey("set_paper_size_custom_width_tips"); - jLabelWidth.setToolTipText(width); - jSpinnerWidth.setToolTipText(width); - jLabelHeight.setText(I18nUtils.localizedStringForKey("set_paper_size_custom_height")); - String height = I18nUtils.localizedStringForKey("set_paper_size_custom_height_tips"); - jLabelHeight.setToolTipText(height); - jSpinnerHeight.setToolTipText(height); - String margin = I18nUtils.localizedStringForKey("set_paper_margins_tips"); - jLabelMarginTop.setText(I18nUtils.localizedStringForKey("set_paper_margins_top")); - jLabelMarginTop.setToolTipText(margin); - jSpinnerMarginTop.setToolTipText(margin); - jLabelMarginLeft.setText(I18nUtils.localizedStringForKey("set_paper_margins_left")); - jLabelMarginLeft.setToolTipText(margin); - jSpinnerMarginLeft.setToolTipText(margin); - jLabelMarginBottom.setText(I18nUtils.localizedStringForKey("set_paper_margins_bottom")); - jLabelMarginBottom.setToolTipText(margin); - jSpinnerMarginBottom.setToolTipText(margin); - jLabelMarginRight.setText(I18nUtils.localizedStringForKey("set_paper_margins_right")); - jLabelMarginRight.setToolTipText(margin); - jSpinnerMarginRight.setToolTipText(margin); - jLabelOverlap.setText(I18nUtils.localizedStringForKey("set_paper_advanced_overlap")); - String overlap = I18nUtils.localizedStringForKey("set_paper_advanced_overlap_tips"); - jLabelOverlap.setToolTipText(overlap); - jSpinnerOverlap.setToolTipText(overlap); - jLabelCrop.setText(I18nUtils.localizedStringForKey("set_paper_advanced_crop")); - String crop = I18nUtils.localizedStringForKey("set_paper_advanced_crop_tips"); - jLabelCrop.setToolTipText(crop); - jSpinnerCrop.setToolTipText(crop); - jButtonImport.setText(I18nUtils.localizedStringForKey("set_paper_actions_import_xml")); - jButtonImport.setToolTipText(I18nUtils.localizedStringForKey("set_paper_actions_import_xml_tip")); - jButtonExport.setText(I18nUtils.localizedStringForKey("set_paper_actions_export_xml")); - jButtonExport.setToolTipText(I18nUtils.localizedStringForKey("set_paper_actions_export_xml_tip")); - jButtonDefaults.setText(I18nUtils.localizedStringForKey("set_paper_actions_restore_default")); - jButtonDefaults.setToolTipText(I18nUtils.localizedStringForKey("set_paper_actions_restore_default_tips")); - importError = I18nUtils.localizedStringForKey("set_paper_actions_error_import"); - exportError = I18nUtils.localizedStringForKey("set_paper_actions_error_export"); - errorReason = I18nUtils.localizedStringForKey("set_paper_actions_error_reason"); - errorTitle = I18nUtils.localizedStringForKey("set_paper_actions_error_title"); - xmlFileFilter = I18nUtils.localizedStringForKey("set_paper_actions_xml_filter"); - } - - private void setUnitSystem(UnitSystem unitSystem) { - if (unitSystem.equals(this.unitSystem)) - return; - this.unitSystem = unitSystem; - Double step = 0.1d; - double min, max; - min = unitSystem.pointsToUnits(SettingsPaperAtlas.MARGIN_MIN); - max = unitSystem.pointsToUnits(SettingsPaperAtlas.MARGIN_MAX); - setModel(modelMarginBottom, min, max, step); - setModel(modelMarginLeft, min, max, step); - setModel(modelMarginRight, min, max, step); - setModel(modelMarginTop, min, max, step); - min = unitSystem.pointsToUnits(SettingsPaperAtlas.PAPER_SIZE_MIN); - max = unitSystem.pointsToUnits(SettingsPaperAtlas.PAPER_SIZE_MAX); - setModel(modelWidth, min, max, step); - setModel(modelHeight, min, max, step); - min = unitSystem.pointsToUnits(SettingsPaperAtlas.OVERLAP_MIN); - max = unitSystem.pointsToUnits(SettingsPaperAtlas.OVERLAP_MAX); - setModel(modelOverlap, min, max, step); - String pattern = "#0.00 " + unitSystem.unitTiny; - setEditor(jSpinnerWidth, pattern); - setEditor(jSpinnerHeight, pattern); - setEditor(jSpinnerMarginTop, pattern); - setEditor(jSpinnerMarginLeft, pattern); - setEditor(jSpinnerMarginBottom, pattern); - setEditor(jSpinnerMarginRight, pattern); - setEditor(jSpinnerOverlap, pattern); - } - - private PaperSize getPaperSize() { - if (jRadioButtonDefault.isSelected()) { - Format format = (Format) jComboBoxFormat.getSelectedItem(); - boolean landscape = jCheckBoxLandscape.isSelected(); - return new PaperSize(format, landscape); - } - if (jRadioButtonCustom.isSelected()) { - double width = modelWidth.getNumber().doubleValue(); - double height = modelHeight.getNumber().doubleValue(); - width = unitSystem.unitsToPoints(width); - height = unitSystem.unitsToPoints(height); - return new PaperSize(width, height); - } - return null; - } - - private void setPaperSize(PaperSize paperSize) { - if (paperSize == null) { - jRadioButtonSelection.setSelected(true); - return; - } - if (paperSize.format != null) { - jRadioButtonDefault.setSelected(true); - jComboBoxFormat.setSelectedIndex(paperSize.format.ordinal()); - jCheckBoxLandscape.setSelected(paperSize.landscape); - } else { - jRadioButtonCustom.setSelected(true); - } - } - - public void loadSettings(Settings s) { - setUnitSystem(s.unitSystem); - loadSettings(s.paperAtlas); - } - - public void loadSettings(SettingsPaperAtlas s) { - setPaperSize(s.paperSize); - modelMarginTop.setValue(unitSystem.pointsToUnits(s.marginTop)); - modelMarginLeft.setValue(unitSystem.pointsToUnits(s.marginLeft)); - modelMarginBottom.setValue(unitSystem.pointsToUnits(s.marginBottom)); - modelMarginRight.setValue(unitSystem.pointsToUnits(s.marginRight)); - jCheckBoxScaleBar.setSelected(s.scaleBar); - jCheckBoxCompass.setSelected(s.compass); - jComboBoxWgsDensity.setSelectedItem(s.wgsDensity); - jCheckBoxWgsGrid.setSelected(s.wgsEnabled); - jCheckBoxPageNumbers.setSelected(s.pageNumbers); - modelCrop.setValue(s.crop); - modelOverlap.setValue(unitSystem.pointsToUnits(s.overlap)); - modelCompression.setValue(s.compression); - modelDpi.setValue(s.dpi); - } - - public void applySettings(Settings s) { - applySettings(s.paperAtlas); - } - - public void applySettings(SettingsPaperAtlas s) { - s.paperSize = getPaperSize(); - s.marginTop = unitSystem.unitsToPoints(modelMarginTop.getNumber().doubleValue()); - s.marginLeft = unitSystem.unitsToPoints(modelMarginLeft.getNumber().doubleValue()); - s.marginBottom = unitSystem.unitsToPoints(modelMarginBottom.getNumber().doubleValue()); - s.marginRight = unitSystem.unitsToPoints(modelMarginRight.getNumber().doubleValue()); - s.scaleBar = jCheckBoxScaleBar.isSelected(); - s.compass = jCheckBoxCompass.isSelected(); - s.wgsDensity = (WgsDensity) jComboBoxWgsDensity.getSelectedItem(); - s.wgsEnabled = jCheckBoxWgsGrid.isSelected(); - s.pageNumbers = jCheckBoxPageNumbers.isSelected(); - s.crop = modelCrop.getNumber().intValue(); - s.overlap = unitSystem.unitsToPoints(modelOverlap.getNumber().doubleValue()); - s.compression = modelCompression.getNumber().intValue(); - s.dpi = modelDpi.getNumber().intValue(); - } -} +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.gui.settings; + +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.JAXBException; +import jakarta.xml.bind.Marshaller; +import jakarta.xml.bind.Unmarshaller; +import mobac.gui.mapview.WgsGrid.WgsDensity; +import mobac.program.model.PaperSize; +import mobac.program.model.PaperSize.Format; +import mobac.program.model.Settings; +import mobac.program.model.SettingsPaperAtlas; +import mobac.program.model.UnitSystem; +import mobac.utilities.GBCTable; +import mobac.utilities.I18nUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.ButtonGroup; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JSpinner; +import javax.swing.SpinnerNumberModel; +import javax.swing.border.TitledBorder; +import javax.swing.filechooser.FileFilter; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.io.File; + +public class SettingsGUIPaper extends JPanel { + private static final long serialVersionUID = -8265562215604604074L; + + private static final Logger LOG = LoggerFactory.getLogger(SettingsGUIPaper.class); + private final JButton jButtonDefaults = new JButton(); + private final JButton jButtonExport = new JButton(); + private final JButton jButtonImport = new JButton(); + private final JCheckBox jCheckBoxCompass = new JCheckBox(); + private final JCheckBox jCheckBoxLandscape = new JCheckBox(); + private final JCheckBox jCheckBoxPageNumbers = new JCheckBox("", true); + private final JCheckBox jCheckBoxScaleBar = new JCheckBox(); + private final JCheckBox jCheckBoxWgsGrid = new JCheckBox("", true); + private final TitledBorder titledBorderActions = SettingsGUI.createSectionBorder(""); + private final TitledBorder titledBorderAdditions = SettingsGUI.createSectionBorder(""); + private final TitledBorder titledBorderAdvanced = SettingsGUI.createSectionBorder(""); + private final TitledBorder titledBorderMargins = SettingsGUI.createSectionBorder(""); + private final TitledBorder titledBorderSize = SettingsGUI.createSectionBorder(""); + private final JPanel jPanelActions = createSection(titledBorderActions), + jPanelAdditions = createSection(titledBorderAdditions), + jPanelAdvanced = createSection(titledBorderAdvanced), jPanelMargins = createSection(titledBorderMargins), + jPanelSize = createSection(titledBorderSize); + private final JComboBox jComboBoxFormat = new JComboBox<>(Format.values()); + private final JComboBox jComboBoxWgsDensity = new JComboBox<>(WgsDensity.values()); + private final JRadioButton jRadioButtonCustom = new JRadioButton("", true); + private final JRadioButton jRadioButtonDefault = new JRadioButton("", true); + private final JRadioButton jRadioButtonSelection = new JRadioButton("", true); + private final SpinnerNumberModel modelCompression = new SpinnerNumberModel(SettingsPaperAtlas.COMPRESSION_DEFAULT, + SettingsPaperAtlas.COMPRESSION_MIN, SettingsPaperAtlas.COMPRESSION_MAX, 1); + private final SpinnerNumberModel modelCrop = new SpinnerNumberModel(SettingsPaperAtlas.CROP_DEFAULT, + SettingsPaperAtlas.CROP_MIN, SettingsPaperAtlas.CROP_MAX, 1), + modelDpi = new SpinnerNumberModel(SettingsPaperAtlas.DPI_DEFAULT, SettingsPaperAtlas.DPI_MIN, + SettingsPaperAtlas.DPI_MAX, 1); + private final SpinnerNumberModel modelHeight = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); + private final SpinnerNumberModel modelWidth = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); + private final SpinnerNumberModel modelMarginBottom = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); + private final SpinnerNumberModel modelMarginLeft = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); + private final SpinnerNumberModel modelMarginRight = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); + private final SpinnerNumberModel modelMarginTop = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); + private final SpinnerNumberModel modelOverlap = new SpinnerNumberModel(0.0, 0.0, 0.0, 1.0); + private final JSpinner jSpinnerDpi = new JSpinner(modelDpi), jSpinnerWidth = new JSpinner(modelWidth), + jSpinnerHeight = new JSpinner(modelHeight), jSpinnerMarginTop = new JSpinner(modelMarginTop), + jSpinnerMarginLeft = new JSpinner(modelMarginLeft), jSpinnerMarginBottom = new JSpinner(modelMarginBottom), + jSpinnerMarginRight = new JSpinner(modelMarginRight), jSpinnerOverlap = new JSpinner(modelOverlap), + jSpinnerCrop = new JSpinner(modelCrop), jSpinnerCompression = new JSpinner(modelCompression); + private final JLabel jLabelCompression = new JLabel(), jLabelDpi = new JLabel(), jLabelWidth = new JLabel(), + jLabelHeight = new JLabel(), jLabelMarginTop = new JLabel(), jLabelMarginLeft = new JLabel(), + jLabelMarginBottom = new JLabel(), jLabelMarginRight = new JLabel(), jLabelOverlap = new JLabel(), + jLabelCrop = new JLabel(); + private JFileChooser jFileChooser; + private String importError, exportError, errorReason, errorTitle, xmlFileFilter; + private UnitSystem unitSystem; + + public SettingsGUIPaper() { + super(new GridBagLayout()); + LOG.debug("Preparing paper atlas settings panel"); + jSpinnerCrop.setEditor(new JSpinner.NumberEditor(jSpinnerCrop, "#0'%'")); + setUnitSystem(UnitSystem.Metric); + i18n(); + jButtonImport.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + importFromXml(); + } + }); + jButtonExport.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + exportToXml(); + } + }); + jButtonDefaults.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + resetToDefaults(); + } + }); + jComboBoxFormat.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + Format format = (Format) jComboBoxFormat.getSelectedItem(); + double width = unitSystem.pointsToUnits(format.width); + double height = unitSystem.pointsToUnits(format.height); + modelWidth.setValue(width); + modelHeight.setValue(height); + } + }); + jCheckBoxWgsGrid.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + boolean enabled = e.getStateChange() != ItemEvent.DESELECTED; + jComboBoxWgsDensity.setEnabled(enabled); + } + }); + jRadioButtonCustom.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + boolean enabled = e.getStateChange() != ItemEvent.DESELECTED; + jLabelWidth.setEnabled(enabled); + jLabelHeight.setEnabled(enabled); + jSpinnerWidth.setEnabled(enabled); + jSpinnerHeight.setEnabled(enabled); + } + }); + jRadioButtonDefault.addItemListener(new ItemListener() { + public void itemStateChanged(ItemEvent e) { + boolean enabled = e.getStateChange() != ItemEvent.DESELECTED; + jComboBoxFormat.setEnabled(enabled); + jCheckBoxLandscape.setEnabled(enabled); + } + }); + + ButtonGroup buttonGroup = new ButtonGroup(); + buttonGroup.add(jRadioButtonSelection); + buttonGroup.add(jRadioButtonDefault); + buttonGroup.add(jRadioButtonCustom); + + GBCTable gbc = new GBCTable(); + + jPanelSize.add(jRadioButtonDefault, gbc.begin()); + jPanelSize.add(jRadioButtonCustom, gbc.incY()); + jPanelSize.add(jRadioButtonSelection, gbc.incY()); + jPanelSize.add(jComboBoxFormat, gbc.incX()); + jPanelSize.add(jLabelWidth, gbc.incY()); + jPanelSize.add(jLabelHeight, gbc.incY()); + jPanelSize.add(jCheckBoxLandscape, gbc.incX()); + jPanelSize.add(jSpinnerWidth, gbc.incY()); + jPanelSize.add(jSpinnerHeight, gbc.incY()); + jPanelSize.add(Box.createGlue(), gbc.incX().gridheight(3).fill()); + + jPanelMargins.add(jLabelMarginTop, gbc.begin()); + jPanelMargins.add(jLabelMarginBottom, gbc.incY()); + jPanelMargins.add(jSpinnerMarginTop, gbc.incX()); + jPanelMargins.add(jSpinnerMarginBottom, gbc.incY()); + jPanelMargins.add(jLabelMarginLeft, gbc.incX()); + jPanelMargins.add(jLabelMarginRight, gbc.incY()); + jPanelMargins.add(jSpinnerMarginLeft, gbc.incX()); + jPanelMargins.add(jSpinnerMarginRight, gbc.incY()); + jPanelMargins.add(Box.createHorizontalGlue(), gbc.incX().fillH()); + + jPanelAdditions.add(jCheckBoxWgsGrid, gbc.begin()); + jPanelAdditions.add(jCheckBoxPageNumbers, gbc.incY().gridwidth(2)); + jPanelAdditions.add(jCheckBoxScaleBar, gbc.incY()); + jPanelAdditions.add(jComboBoxWgsDensity, gbc.incX()); + gbc.incY(); + jPanelAdditions.add(jCheckBoxCompass, gbc.incY()); + jPanelAdditions.add(Box.createHorizontalGlue(), gbc.incX().fillH()); + + jPanelAdvanced.add(jLabelDpi, gbc.begin()); + jPanelAdvanced.add(jLabelCompression, gbc.incY()); + jPanelAdvanced.add(jSpinnerDpi, gbc.incX()); + jPanelAdvanced.add(jSpinnerCompression, gbc.incY()); + jPanelAdvanced.add(jLabelOverlap, gbc.incX()); + jPanelAdvanced.add(jLabelCrop, gbc.incY()); + jPanelAdvanced.add(jSpinnerOverlap, gbc.incX()); + jPanelAdvanced.add(jSpinnerCrop, gbc.incY()); + jPanelAdvanced.add(Box.createHorizontalGlue(), gbc.incX().fillH()); + + jPanelActions.add(jButtonImport, gbc.begin()); + jPanelActions.add(jButtonExport, gbc.incX()); + jPanelActions.add(jButtonDefaults, gbc.incX()); + jPanelActions.add(Box.createHorizontalGlue(), gbc.incX().fillH()); + + gbc = new GBCTable(0); + setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + add(jPanelSize, gbc.begin()); + add(jPanelMargins, gbc.incY()); + add(jPanelAdditions, gbc.incX().fillH()); + add(jPanelAdvanced, gbc.incY().fillH()); + add(jPanelActions, gbc.begin(1, 3).gridwidth(2).fillH()); + add(Box.createGlue(), gbc.incY().gridwidth(2).fill()); + } + + private static void setModel(SpinnerNumberModel model, double min, double max, Double step) { + model.setMaximum(max); + model.setMinimum(min); + model.setStepSize(step); + double value = model.getNumber().doubleValue(); + value = Math.max(Math.min(value, max), min); + model.setValue(value); + } + + private static void setEditor(JSpinner jSpinner, String pattern) { + jSpinner.setEditor(new JSpinner.NumberEditor(jSpinner, pattern)); + } + + private static JPanel createSection(TitledBorder border) { + JPanel jPanel = new JPanel(new GridBagLayout()); + jPanel.setBorder(border); + return jPanel; + } + + private void prepareFileChooser() { + if (jFileChooser == null) { + jFileChooser = new JFileChooser(); + jFileChooser.setFileFilter(new FileFilter() { + @Override + public boolean accept(File f) { + return f.isDirectory() || f.getName().endsWith(".xml"); + } + + @Override + public String getDescription() { + return xmlFileFilter; + } + }); + } + } + + private void importFromXml() { + prepareFileChooser(); + int state = jFileChooser.showOpenDialog(SettingsGUIPaper.this); + if (state == JFileChooser.APPROVE_OPTION) { + File file = jFileChooser.getSelectedFile(); + JAXBContext context; + try { + context = JAXBContext.newInstance(SettingsPaperAtlas.class); + Unmarshaller um = context.createUnmarshaller(); + SettingsPaperAtlas s = (SettingsPaperAtlas) um.unmarshal(file); + loadSettings(s); + } catch (JAXBException ex) { + String text = importError + file.getName() + "\n" + errorReason + ex.getMessage(); + JOptionPane.showMessageDialog(SettingsGUIPaper.this, text, errorTitle, JOptionPane.ERROR_MESSAGE); + } + } + } + + private void exportToXml() { + prepareFileChooser(); + int state = jFileChooser.showSaveDialog(SettingsGUIPaper.this); + if (state == JFileChooser.APPROVE_OPTION) { + File file = jFileChooser.getSelectedFile(); + try { + JAXBContext context = JAXBContext.newInstance(SettingsPaperAtlas.class); + Marshaller m = context.createMarshaller(); + SettingsPaperAtlas s = new SettingsPaperAtlas(); + applySettings(s); + m.marshal(s, file); + } catch (JAXBException ex) { + String text = exportError + file.getName() + "\n" + errorReason + ex.getMessage(); + LOG.error(text); + JOptionPane.showMessageDialog(SettingsGUIPaper.this, text, errorTitle, JOptionPane.ERROR_MESSAGE); + } + } + } + + private void resetToDefaults() { + loadSettings(new SettingsPaperAtlas()); + } + + private void i18n() { + setName(I18nUtils.localizedStringForKey("set_paper_title")); + titledBorderActions.setTitle(I18nUtils.localizedStringForKey("set_paper_actions")); + titledBorderAdditions.setTitle(I18nUtils.localizedStringForKey("set_paper_additions")); + titledBorderAdvanced.setTitle(I18nUtils.localizedStringForKey("set_paper_advanced")); + titledBorderMargins.setTitle(I18nUtils.localizedStringForKey("set_paper_margins")); + titledBorderSize.setTitle(I18nUtils.localizedStringForKey("set_paper_size")); + jComboBoxFormat.setToolTipText(I18nUtils.localizedStringForKey("set_paper_size_default_format_tips")); + jComboBoxWgsDensity.setToolTipText(I18nUtils.localizedStringForKey("set_paper_wgs_grid_density_tips")); + jRadioButtonSelection.setText(I18nUtils.localizedStringForKey("set_paper_size_selection")); + jRadioButtonSelection.setToolTipText(I18nUtils.localizedStringForKey("set_paper_size_selection_tips")); + jRadioButtonDefault.setText(I18nUtils.localizedStringForKey("set_paper_size_default")); + jRadioButtonDefault.setToolTipText(I18nUtils.localizedStringForKey("set_paper_size_default_tips")); + jRadioButtonCustom.setText(I18nUtils.localizedStringForKey("set_paper_size_custom")); + jRadioButtonCustom.setToolTipText(I18nUtils.localizedStringForKey("set_paper_size_custom_tips")); + jCheckBoxScaleBar.setText(I18nUtils.localizedStringForKey("set_paper_scale_bar")); + jCheckBoxScaleBar.setToolTipText(I18nUtils.localizedStringForKey("set_paper_scale_tips")); + jCheckBoxCompass.setText(I18nUtils.localizedStringForKey("set_paper_compass")); + jCheckBoxCompass.setToolTipText(I18nUtils.localizedStringForKey("set_paper_compass_tips")); + jCheckBoxLandscape.setText(I18nUtils.localizedStringForKey("set_paper_size_default_landscape")); + jCheckBoxLandscape.setToolTipText(I18nUtils.localizedStringForKey("set_paper_size_default_landscape_tips")); + jCheckBoxWgsGrid.setText(I18nUtils.localizedStringForKey("set_paper_wgs_grid")); + jCheckBoxWgsGrid.setToolTipText(I18nUtils.localizedStringForKey("set_paper_wgs_grid_tips")); + jCheckBoxPageNumbers.setText(I18nUtils.localizedStringForKey("set_paper_paper_nubmer")); + jCheckBoxPageNumbers.setToolTipText(I18nUtils.localizedStringForKey("set_paper_paper_nubmer_tips")); + jLabelCompression.setText(I18nUtils.localizedStringForKey("set_paper_advanced_compression")); + String compression = I18nUtils.localizedStringForKey("set_paper_advanced_compression_tips"); + jLabelCompression.setToolTipText(compression); + jSpinnerCompression.setToolTipText(compression); + jLabelDpi.setText(I18nUtils.localizedStringForKey("set_paper_advanced_dpi")); + String dpi = I18nUtils.localizedStringForKey("set_paper_advanced_dpi_tips"); + jLabelDpi.setToolTipText(dpi); + jSpinnerDpi.setToolTipText(dpi); + jLabelWidth.setText(I18nUtils.localizedStringForKey("set_paper_size_custom_width")); + String width = I18nUtils.localizedStringForKey("set_paper_size_custom_width_tips"); + jLabelWidth.setToolTipText(width); + jSpinnerWidth.setToolTipText(width); + jLabelHeight.setText(I18nUtils.localizedStringForKey("set_paper_size_custom_height")); + String height = I18nUtils.localizedStringForKey("set_paper_size_custom_height_tips"); + jLabelHeight.setToolTipText(height); + jSpinnerHeight.setToolTipText(height); + String margin = I18nUtils.localizedStringForKey("set_paper_margins_tips"); + jLabelMarginTop.setText(I18nUtils.localizedStringForKey("set_paper_margins_top")); + jLabelMarginTop.setToolTipText(margin); + jSpinnerMarginTop.setToolTipText(margin); + jLabelMarginLeft.setText(I18nUtils.localizedStringForKey("set_paper_margins_left")); + jLabelMarginLeft.setToolTipText(margin); + jSpinnerMarginLeft.setToolTipText(margin); + jLabelMarginBottom.setText(I18nUtils.localizedStringForKey("set_paper_margins_bottom")); + jLabelMarginBottom.setToolTipText(margin); + jSpinnerMarginBottom.setToolTipText(margin); + jLabelMarginRight.setText(I18nUtils.localizedStringForKey("set_paper_margins_right")); + jLabelMarginRight.setToolTipText(margin); + jSpinnerMarginRight.setToolTipText(margin); + jLabelOverlap.setText(I18nUtils.localizedStringForKey("set_paper_advanced_overlap")); + String overlap = I18nUtils.localizedStringForKey("set_paper_advanced_overlap_tips"); + jLabelOverlap.setToolTipText(overlap); + jSpinnerOverlap.setToolTipText(overlap); + jLabelCrop.setText(I18nUtils.localizedStringForKey("set_paper_advanced_crop")); + String crop = I18nUtils.localizedStringForKey("set_paper_advanced_crop_tips"); + jLabelCrop.setToolTipText(crop); + jSpinnerCrop.setToolTipText(crop); + jButtonImport.setText(I18nUtils.localizedStringForKey("set_paper_actions_import_xml")); + jButtonImport.setToolTipText(I18nUtils.localizedStringForKey("set_paper_actions_import_xml_tip")); + jButtonExport.setText(I18nUtils.localizedStringForKey("set_paper_actions_export_xml")); + jButtonExport.setToolTipText(I18nUtils.localizedStringForKey("set_paper_actions_export_xml_tip")); + jButtonDefaults.setText(I18nUtils.localizedStringForKey("set_paper_actions_restore_default")); + jButtonDefaults.setToolTipText(I18nUtils.localizedStringForKey("set_paper_actions_restore_default_tips")); + importError = I18nUtils.localizedStringForKey("set_paper_actions_error_import"); + exportError = I18nUtils.localizedStringForKey("set_paper_actions_error_export"); + errorReason = I18nUtils.localizedStringForKey("set_paper_actions_error_reason"); + errorTitle = I18nUtils.localizedStringForKey("set_paper_actions_error_title"); + xmlFileFilter = I18nUtils.localizedStringForKey("set_paper_actions_xml_filter"); + } + + private void setUnitSystem(UnitSystem unitSystem) { + if (unitSystem.equals(this.unitSystem)) { + return; + } + this.unitSystem = unitSystem; + Double step = 0.1d; + double min, max; + min = unitSystem.pointsToUnits(SettingsPaperAtlas.MARGIN_MIN); + max = unitSystem.pointsToUnits(SettingsPaperAtlas.MARGIN_MAX); + setModel(modelMarginBottom, min, max, step); + setModel(modelMarginLeft, min, max, step); + setModel(modelMarginRight, min, max, step); + setModel(modelMarginTop, min, max, step); + min = unitSystem.pointsToUnits(SettingsPaperAtlas.PAPER_SIZE_MIN); + max = unitSystem.pointsToUnits(SettingsPaperAtlas.PAPER_SIZE_MAX); + setModel(modelWidth, min, max, step); + setModel(modelHeight, min, max, step); + min = unitSystem.pointsToUnits(SettingsPaperAtlas.OVERLAP_MIN); + max = unitSystem.pointsToUnits(SettingsPaperAtlas.OVERLAP_MAX); + setModel(modelOverlap, min, max, step); + String pattern = "#0.00 " + unitSystem.unitTiny; + setEditor(jSpinnerWidth, pattern); + setEditor(jSpinnerHeight, pattern); + setEditor(jSpinnerMarginTop, pattern); + setEditor(jSpinnerMarginLeft, pattern); + setEditor(jSpinnerMarginBottom, pattern); + setEditor(jSpinnerMarginRight, pattern); + setEditor(jSpinnerOverlap, pattern); + } + + private PaperSize getPaperSize() { + if (jRadioButtonDefault.isSelected()) { + Format format = (Format) jComboBoxFormat.getSelectedItem(); + boolean landscape = jCheckBoxLandscape.isSelected(); + return new PaperSize(format, landscape); + } + if (jRadioButtonCustom.isSelected()) { + double width = modelWidth.getNumber().doubleValue(); + double height = modelHeight.getNumber().doubleValue(); + width = unitSystem.unitsToPoints(width); + height = unitSystem.unitsToPoints(height); + return new PaperSize(width, height); + } + return null; + } + + private void setPaperSize(PaperSize paperSize) { + if (paperSize == null) { + jRadioButtonSelection.setSelected(true); + return; + } + if (paperSize.format != null) { + jRadioButtonDefault.setSelected(true); + jComboBoxFormat.setSelectedIndex(paperSize.format.ordinal()); + jCheckBoxLandscape.setSelected(paperSize.landscape); + } else { + jRadioButtonCustom.setSelected(true); + } + } + + public void loadSettings(Settings s) { + setUnitSystem(s.unitSystem); + loadSettings(s.paperAtlas); + } + + public void loadSettings(SettingsPaperAtlas s) { + setPaperSize(s.paperSize); + modelMarginTop.setValue(unitSystem.pointsToUnits(s.marginTop)); + modelMarginLeft.setValue(unitSystem.pointsToUnits(s.marginLeft)); + modelMarginBottom.setValue(unitSystem.pointsToUnits(s.marginBottom)); + modelMarginRight.setValue(unitSystem.pointsToUnits(s.marginRight)); + jCheckBoxScaleBar.setSelected(s.scaleBar); + jCheckBoxCompass.setSelected(s.compass); + jComboBoxWgsDensity.setSelectedItem(s.wgsDensity); + jCheckBoxWgsGrid.setSelected(s.wgsEnabled); + jCheckBoxPageNumbers.setSelected(s.pageNumbers); + modelCrop.setValue(s.crop); + modelOverlap.setValue(unitSystem.pointsToUnits(s.overlap)); + modelCompression.setValue(s.compression); + modelDpi.setValue(s.dpi); + } + + public void applySettings(Settings s) { + applySettings(s.paperAtlas); + } + + public void applySettings(SettingsPaperAtlas s) { + s.paperSize = getPaperSize(); + s.marginTop = unitSystem.unitsToPoints(modelMarginTop.getNumber().doubleValue()); + s.marginLeft = unitSystem.unitsToPoints(modelMarginLeft.getNumber().doubleValue()); + s.marginBottom = unitSystem.unitsToPoints(modelMarginBottom.getNumber().doubleValue()); + s.marginRight = unitSystem.unitsToPoints(modelMarginRight.getNumber().doubleValue()); + s.scaleBar = jCheckBoxScaleBar.isSelected(); + s.compass = jCheckBoxCompass.isSelected(); + s.wgsDensity = (WgsDensity) jComboBoxWgsDensity.getSelectedItem(); + s.wgsEnabled = jCheckBoxWgsGrid.isSelected(); + s.pageNumbers = jCheckBoxPageNumbers.isSelected(); + s.crop = modelCrop.getNumber().intValue(); + s.overlap = unitSystem.unitsToPoints(modelOverlap.getNumber().doubleValue()); + s.compression = modelCompression.getNumber().intValue(); + s.dpi = modelDpi.getNumber().intValue(); + } +} diff --git a/src/main/java/mobac/gui/settings/SettingsGUITileStore.java b/mobac/src/main/java/mobac/gui/settings/SettingsGUITileStore.java similarity index 82% rename from src/main/java/mobac/gui/settings/SettingsGUITileStore.java rename to mobac/src/main/java/mobac/gui/settings/SettingsGUITileStore.java index 1a8b7a4..0fdba7a 100644 --- a/src/main/java/mobac/gui/settings/SettingsGUITileStore.java +++ b/mobac/src/main/java/mobac/gui/settings/SettingsGUITileStore.java @@ -1,30 +1,30 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.settings; -import java.awt.BorderLayout; -import java.awt.Dimension; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.Insets; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.LinkedList; -import java.util.List; +import mobac.mapsources.MapSourcesManager; +import mobac.program.interfaces.MapSource; +import mobac.program.tilestore.TileStore; +import mobac.program.tilestore.TileStoreInfo; +import mobac.program.tilestore.berkeleydb.DelayedInterruptThread; +import mobac.utilities.I18nUtils; +import mobac.utilities.Utilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.swing.BorderFactory; import javax.swing.ImageIcon; @@ -36,35 +36,38 @@ import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.SwingUtilities; import javax.swing.border.BevelBorder; - -import mobac.mapsources.MapSourcesManager; -import mobac.program.interfaces.MapSource; -import mobac.program.tilestore.TileStore; -import mobac.program.tilestore.TileStoreInfo; -import mobac.program.tilestore.berkeleydb.DelayedInterruptThread; -import mobac.utilities.I18nUtils; -import mobac.utilities.Utilities; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.LinkedList; +import java.util.List; public class SettingsGUITileStore extends JPanel { + private static final Logger LOG = LoggerFactory.getLogger(SettingsGUITileStore.class); + public final JCheckBox tileStoreEnabled; private final JPanel tileStoreInfoPanel; - - private List tileStoreInfoList = new LinkedList(); + private final List tileStoreInfoList = new LinkedList<>(); + protected DelayedInterruptThread tileStoreAsyncThread = null; private JLabel totalTileCountLabel; private JLabel totalTileSizeLabel; - protected DelayedInterruptThread tileStoreAsyncThread = null; - public SettingsGUITileStore(SettingsGUI gui) { super(); + LOG.debug("Preparing SettingsGUITileStore"); gui.addTab(I18nUtils.localizedStringForKey("set_tile_store_title"), this); tileStoreEnabled = new JCheckBox(I18nUtils.localizedStringForKey("set_tile_store_enable_checkbox")); JPanel tileStorePanel = new JPanel(new BorderLayout()); - tileStorePanel.setBorder(SettingsGUI.createSectionBorder(I18nUtils.localizedStringForKey("set_tile_store_settings"))); + tileStorePanel + .setBorder(SettingsGUI.createSectionBorder(I18nUtils.localizedStringForKey("set_tile_store_settings"))); tileStorePanel.add(tileStoreEnabled, BorderLayout.CENTER); tileStoreInfoPanel = new JPanel(new GridBagLayout()); // tileStoreInfoPanel.setBorder(createSectionBorder("Information")); @@ -78,15 +81,16 @@ public class SettingsGUITileStore extends JPanel { tileStoreInfoPanel.setMinimumSize(new Dimension(200, 300)); // scrollPane.setMinimumSize(new Dimension(100, 100)); scrollPane.setPreferredSize(new Dimension(520, 100)); - scrollPane.setBorder(SettingsGUI.createSectionBorder(I18nUtils.localizedStringForKey("set_tile_store_information"))); + scrollPane.setBorder( + SettingsGUI.createSectionBorder(I18nUtils.localizedStringForKey("set_tile_store_information"))); add(scrollPane, BorderLayout.CENTER); } /** - * * @param updateStoreName - * name of the tile store to update or null in case of all tile stores to be updated + * name of the tile store to update or null in case of + * all tile stores to be updated */ private void updateTileStoreInfoPanel(String updateStoreName) { try { @@ -120,7 +124,7 @@ public class SettingsGUITileStore extends JPanel { totalTileCount += count; totalTileSize += size; } - final String totalTileCountText = "" + Long.toString(totalTileCount) + ""; + final String totalTileCountText = "" + totalTileCount + ""; final String totalTileSizeText = "" + Utilities.formatBytes(totalTileSize) + ""; SwingUtilities.invokeLater(new Runnable() { public void run() { @@ -129,24 +133,26 @@ public class SettingsGUITileStore extends JPanel { } }); } catch (InterruptedException e) { - SettingsGUI.log.debug("Tile store information retrieval was canceled"); + LOG.debug("Tile store information retrieval was canceled"); } } synchronized void updateTileStoreInfoPanelAsync(final String storeName) { - if (tileStoreAsyncThread != null) + if (tileStoreAsyncThread != null) { return; // An update is currently running + } tileStoreAsyncThread = new DelayedInterruptThread("TileStoreInfoRetriever") { @Override public void run() { - if (storeName == null) - SettingsGUI.log.debug("Updating tilestore information in background"); - else - SettingsGUI.log.debug("Updating tilestore information for \"" + storeName + "\" in background"); + if (storeName == null) { + LOG.debug("Updating tilestore information in background"); + } else { + LOG.debug("Updating tilestore information for \"" + storeName + "\" in background"); + } updateTileStoreInfoPanel(storeName); - SettingsGUI.log.debug("Updating tilestore information finished"); + LOG.debug("Updating tilestore information finished"); tileStoreAsyncThread = null; } }; @@ -167,7 +173,8 @@ public class SettingsGUITileStore extends JPanel { TileStore tileStore = TileStore.getInstance(); MapSourcesManager mapSourcesManager = MapSourcesManager.getInstance(); - tileStoreInfoPanel.add(new JLabel(I18nUtils.localizedStringForKey("set_tile_store_info_mapsrc")), gbc_mapSource); + tileStoreInfoPanel.add(new JLabel(I18nUtils.localizedStringForKey("set_tile_store_info_mapsrc")), + gbc_mapSource); tileStoreInfoPanel.add(new JLabel(I18nUtils.localizedStringForKey("set_tile_store_info_tiles")), gbc_mapTiles); tileStoreInfoPanel.add(new JLabel(I18nUtils.localizedStringForKey("set_tile_store_info_size")), gbc_eol); @@ -178,10 +185,12 @@ public class SettingsGUITileStore extends JPanel { String mapTileSizeText = " ? "; MapSource mapSource = mapSourcesManager.getSourceByName(name); final JLabel mapSourceNameLabel; - if (mapSource != null) + if (mapSource != null) { mapSourceNameLabel = new JLabel(name); - else - mapSourceNameLabel = new JLabel(name + I18nUtils.localizedStringForKey("set_tile_store_info_disabled_subfix")); + } else { + mapSourceNameLabel = new JLabel( + name + I18nUtils.localizedStringForKey("set_tile_store_info_disabled_subfix")); + } final JLabel mapTileCountLabel = new JLabel(mapTileCountText); final JLabel mapTileSizeLabel = new JLabel(mapTileSizeText); final JButton deleteButton = new JButton(trash); @@ -191,7 +200,8 @@ public class SettingsGUITileStore extends JPanel { info.sizeLabel = mapTileSizeLabel; tileStoreInfoList.add(info); deleteButton.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); - deleteButton.setToolTipText(String.format(I18nUtils.localizedStringForKey("set_tile_store_info_delete_tips"), name)); + deleteButton.setToolTipText( + String.format(I18nUtils.localizedStringForKey("set_tile_store_info_delete_tips"), name)); deleteButton.addActionListener(new ClearTileCacheAction(name)); tileStoreInfoPanel.add(mapSourceNameLabel, gbc_mapSource); @@ -216,8 +226,9 @@ public class SettingsGUITileStore extends JPanel { public void stopThread() { Thread t = tileStoreAsyncThread; - if (t != null) + if (t != null) { t.interrupt(); + } } private static class TileSourceInfoComponents { @@ -251,7 +262,7 @@ public class SettingsGUITileStore extends JPanel { SettingsGUITileStore.this.updateTileStoreInfoPanelAsync(storeName); SettingsGUITileStore.this.repaint(); } catch (Exception e) { - SettingsGUI.log.error("An error occured while cleaning tile cache: ", e); + LOG.error("An error occured while cleaning tile cache: ", e); } } }; diff --git a/src/main/java/mobac/gui/settings/SettingsGUIWgsGrid.java b/mobac/src/main/java/mobac/gui/settings/SettingsGUIWgsGrid.java similarity index 89% rename from src/main/java/mobac/gui/settings/SettingsGUIWgsGrid.java rename to mobac/src/main/java/mobac/gui/settings/SettingsGUIWgsGrid.java index 44e13b8..ce5a2ed 100644 --- a/src/main/java/mobac/gui/settings/SettingsGUIWgsGrid.java +++ b/mobac/src/main/java/mobac/gui/settings/SettingsGUIWgsGrid.java @@ -1,28 +1,28 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.gui.settings; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.GridBagLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; +import mobac.gui.dialogs.FontChooser; +import mobac.program.model.Settings; +import mobac.program.model.SettingsWgsGrid; +import mobac.utilities.GBCTable; +import mobac.utilities.I18nUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.swing.BorderFactory; import javax.swing.Box; @@ -33,17 +33,20 @@ import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; - -import mobac.gui.dialogs.FontChooser; -import mobac.program.model.Settings; -import mobac.program.model.SettingsWgsGrid; -import mobac.utilities.GBCTable; -import mobac.utilities.I18nUtils; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.GridBagLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; public class SettingsGUIWgsGrid extends JPanel { private static final long serialVersionUID = -3067609813682787669L; + private static final Logger LOG = LoggerFactory.getLogger(SettingsGUIWgsGrid.class); + private final FontChooser fontChooser = new FontChooser(); private final JButton jButtonFont = new JButton(FontChooser.encodeFont(FontChooser.DEFAULT)); @@ -56,12 +59,15 @@ public class SettingsGUIWgsGrid extends JPanel { private final JSpinner jSpinnerWidth = new JSpinner(modelWidth); - private JLabel jLabelColor = new JLabel(), jLabelFont = new JLabel(), jLabelWidth = new JLabel(); + private final JLabel jLabelColor = new JLabel(); + private final JLabel jLabelFont = new JLabel(); + private final JLabel jLabelWidth = new JLabel(); private String title; public SettingsGUIWgsGrid() { super(new GridBagLayout()); + LOG.debug("Preparing SettingsGUIWgsGrid"); i18n(); jButtonFont.addActionListener(new ActionListener() { @@ -111,7 +117,7 @@ public class SettingsGUIWgsGrid extends JPanel { jCheckBoxCompressLabels.setText(I18nUtils.localizedStringForKey("set_display_grid_compress")); jCheckBoxCompressLabels.setToolTipText(I18nUtils.localizedStringForKey("set_display_grid_compress_tips")); setBorder(SettingsGUI.createSectionBorder(I18nUtils.localizedStringForKey("set_display_grid"))); - title = I18nUtils.localizedStringForKey("set_display_grid_title");//TODO: recovery + title = I18nUtils.localizedStringForKey("set_display_grid_title");// TODO: recovery jLabelWidth.setText(I18nUtils.localizedStringForKey("set_display_grid_width")); String width = I18nUtils.localizedStringForKey("set_display_grid_width_tips"); jLabelWidth.setToolTipText(width); diff --git a/src/main/java/mobac/optional/JavaAdvancedImaging.java b/mobac/src/main/java/mobac/optional/JavaAdvancedImaging.java similarity index 77% rename from src/main/java/mobac/optional/JavaAdvancedImaging.java rename to mobac/src/main/java/mobac/optional/JavaAdvancedImaging.java index 50d28d9..48e102b 100644 --- a/src/main/java/mobac/optional/JavaAdvancedImaging.java +++ b/mobac/src/main/java/mobac/optional/JavaAdvancedImaging.java @@ -1,45 +1,42 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.optional; -import java.awt.Color; -import java.awt.Graphics; -import java.awt.image.BufferedImage; - import javax.media.jai.RenderedOp; import javax.media.jai.operator.ColorQuantizerDescriptor; +import java.awt.Graphics; +import java.awt.image.BufferedImage; /** * Centralizes all methods that require the optional Java Advanced Imaging * library. - * */ public class JavaAdvancedImaging { // private static final Logger log = - // Logger.getLogger(JavaAdvancedImaging.class); + // LoggerFactory.getLogger(JavaAdvancedImaging.class); public static BufferedImage colorReduceMedianCut(BufferedImage image, int colorCount) { int pixelBits = image.getColorModel().getPixelSize(); if (pixelBits != 24) { /* - * For preventing the javax.media.jai.util.ImagingException: All - * factories fail for the operation "ColorQuantizer" we have to - * create a "compatible" (e.g. TYPE_3BYTE_BGR) BufferedImage + * For preventing the javax.media.jai.util.ImagingException: All factories fail + * for the operation "ColorQuantizer" we have to create a "compatible" (e.g. + * TYPE_3BYTE_BGR) BufferedImage */ BufferedImage trueColorImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR); @@ -48,9 +45,9 @@ public class JavaAdvancedImaging { g.dispose(); image = trueColorImage; } - RenderedOp ro = ColorQuantizerDescriptor.create(image, ColorQuantizerDescriptor.MEDIANCUT, // - new Integer(colorCount), // Max number of colors - null, null, new Integer(1), Integer.valueOf(1), null); + RenderedOp ro = ColorQuantizerDescriptor.create(image, ColorQuantizerDescriptor.MEDIANCUT, // + colorCount, // Max number of colors + null, null, 1, 1, null); return ro.getAsBufferedImage(); } } diff --git a/src/main/java/mobac/program/AtlasThread.java b/mobac/src/main/java/mobac/program/AtlasThread.java similarity index 59% rename from src/main/java/mobac/program/AtlasThread.java rename to mobac/src/main/java/mobac/program/AtlasThread.java index 9d545ec..78963b5 100644 --- a/src/main/java/mobac/program/AtlasThread.java +++ b/mobac/src/main/java/mobac/program/AtlasThread.java @@ -12,21 +12,15 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program; -import java.awt.Toolkit; -import java.io.File; -import java.io.IOException; - -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapDownloadSkippedException; import mobac.gui.AtlasProgress; import mobac.gui.AtlasProgress.AtlasCreationController; +import mobac.mapsources.AbstractMultiLayerMapSource; import mobac.program.atlascreators.AtlasCreator; import mobac.program.atlascreators.tileprovider.DownloadedTileProvider; import mobac.program.atlascreators.tileprovider.FilteredMapSourceProvider; @@ -36,10 +30,12 @@ import mobac.program.interfaces.AtlasInterface; import mobac.program.interfaces.DownloadJobListener; import mobac.program.interfaces.DownloadableElement; import mobac.program.interfaces.FileBasedMapSource; +import mobac.program.interfaces.InitializableMapSource; import mobac.program.interfaces.LayerInterface; import mobac.program.interfaces.MapInterface; import mobac.program.interfaces.MapSource; import mobac.program.interfaces.MapSource.LoadMethod; +import mobac.program.interfaces.MapSourceCallerThreadInfo; import mobac.program.model.AtlasOutputFormat; import mobac.program.model.Settings; import mobac.program.tilestore.TileStore; @@ -48,38 +44,49 @@ import mobac.utilities.I18nUtils; import mobac.utilities.Utilities; import mobac.utilities.tar.TarIndex; import mobac.utilities.tar.TarIndexedArchive; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Logger; +import javax.imageio.ImageIO; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import java.awt.Toolkit; +import java.io.File; +import java.io.IOException; -public class AtlasThread extends Thread implements DownloadJobListener, AtlasCreationController { +public class AtlasThread extends Thread + implements + DownloadJobListener, + AtlasCreationController, + MapSourceCallerThreadInfo { - private static final Logger log = Logger.getLogger(AtlasThread.class); + private static final Logger LOG = LoggerFactory.getLogger(AtlasThread.class); private static int threadNum = 0; - private File customAtlasDir = null; private boolean quitMobacAfterAtlasCreation = false; - - private DownloadJobProducerThread djp = null; + private DownloadJobProducerThread downloadJobProducerThread = null; private JobDispatcher downloadJobDispatcher; - private AtlasProgress ap; // The GUI showing the progress - - private AtlasInterface atlas; + private final AtlasProgress atlasProgress; // The GUI showing the progress + private final AtlasInterface atlas; private AtlasCreator atlasCreator = null; - private PauseResumeHandler pauseResumeHandler; - + private final PauseResumeHandler pauseResumeHandler; private int activeDownloads = 0; private int jobsCompleted = 0; private int jobsRetryError = 0; private int jobsPermanentError = 0; private int maxDownloadRetries = 1; + { + ImageIO.setUseCache(false); + } + public AtlasThread(AtlasInterface atlas) throws AtlasTestException { this(atlas, atlas.getOutputFormat().createAtlasCreatorInstance()); } public AtlasThread(AtlasInterface atlas, AtlasCreator atlasCreator) throws AtlasTestException { super("AtlasThread " + getNextThreadNum()); - ap = new AtlasProgress(this); + atlasProgress = new AtlasProgress(this); this.atlas = atlas; this.atlasCreator = atlasCreator; testAtlas(); @@ -88,14 +95,40 @@ public class AtlasThread extends Thread implements DownloadJobListener, AtlasCre pauseResumeHandler = new PauseResumeHandler(); } + private static synchronized int getNextThreadNum() { + threadNum++; + return threadNum; + } + + private static long getFileBasedTileCount(MapInterface map) { + MapSource mapSource = map.getMapSource(); + if (mapSource instanceof FileBasedMapSource) { + return map.calculateTilesToDownload(); + } + if (mapSource instanceof AbstractMultiLayerMapSource) { + long result = 0; + AbstractMultiLayerMapSource mlMapSource = (AbstractMultiLayerMapSource) mapSource; + long tilesPerLayer = map.calculateTilesToDownload() / mlMapSource.getLayerMapSources().length; + for (MapSource ms : mlMapSource) { + // check all layers if they are file-based + if (ms instanceof FileBasedMapSource) { + result += tilesPerLayer; + } + } + return result; + } + return 0; + } + private void testAtlas() throws AtlasTestException { try { for (LayerInterface layer : atlas) { for (MapInterface map : layer) { MapSource mapSource = map.getMapSource(); - if (!atlasCreator.testMapSource(mapSource)) + if (!atlasCreator.testMapSource(mapSource)) { throw new AtlasTestException("The selected atlas output format \"" + atlas.getOutputFormat() - + "\" does not support the map source \"" + map.getMapSource() + "\""); + + "\" does not support the map source \"" + map.getMapSource() + "\"", map); + } } } } catch (AtlasTestException e) { @@ -105,47 +138,45 @@ public class AtlasThread extends Thread implements DownloadJobListener, AtlasCre } } - private static synchronized int getNextThreadNum() { - threadNum++; - return threadNum; - } - public void run() { GUIExceptionHandler.registerForCurrentThread(); - log.info("Starting creation of " + atlas.getOutputFormat() + " atlas \"" + atlas.getName() + "\""); - if (customAtlasDir != null) - log.debug("Target directory: " + customAtlasDir); - ap.setDownloadControlerListener(this); + LOG.info("Starting creation of {} atlas \"{}\"", atlas.getOutputFormat(), atlas.getName()); + if (customAtlasDir != null) { + LOG.debug("Target directory: {}", customAtlasDir); + } + atlasProgress.setDownloadControllerListener(this); try { createAtlas(); - log.info("Altas creation finished"); - if (quitMobacAfterAtlasCreation) + LOG.info("Atlas creation finished"); + if (quitMobacAfterAtlasCreation) { System.exit(0); + } } catch (OutOfMemoryError e) { System.gc(); SwingUtilities.invokeLater(new Runnable() { public void run() { String message = I18nUtils.localizedStringForKey("msg_out_of_memory_head"); int maxMem = Utilities.getJavaMaxHeapMB(); - if (maxMem > 0) + if (maxMem > 0) { message += String.format(I18nUtils.localizedStringForKey("msg_out_of_memory_detail"), maxMem); + } JOptionPane.showMessageDialog(null, message, I18nUtils.localizedStringForKey("msg_out_of_memory_title"), JOptionPane.ERROR_MESSAGE); - ap.closeWindow(); + atlasProgress.closeWindow(); } }); - log.error("Out of memory: ", e); + LOG.error("Out of memory: ", e); } catch (InterruptedException e) { SwingUtilities.invokeLater(new Runnable() { public void run() { JOptionPane.showMessageDialog(null, I18nUtils.localizedStringForKey("msg_atlas_download_abort"), I18nUtils.localizedStringForKey("Information"), JOptionPane.INFORMATION_MESSAGE); - ap.closeWindow(); + atlasProgress.closeWindow(); } }); - log.info("Altas creation was interrupted by user"); + LOG.info("Atlas creation was interrupted by user"); } catch (Exception e) { - log.error("Altas creation aborted because of an error: ", e); + LOG.error("Atlas creation aborted because of an error: ", e); GUIExceptionHandler.showExceptionDialog(e); } System.gc(); @@ -168,16 +199,15 @@ public class AtlasThread extends Thread implements DownloadJobListener, AtlasCre for (LayerInterface l : atlas) { for (MapInterface m : l) { // Offline map sources are not relevant for the maximum tile limit. - if (m.getMapSource() instanceof FileBasedMapSource) - totalNrOfOnlineTiles -= m.calculateTilesToDownload(); + totalNrOfOnlineTiles -= getFileBasedTileCount(m); } } - if (totalNrOfOnlineTiles > 1000000) { - // NumberFormat f = DecimalFormat.getInstance(); - JOptionPane.showMessageDialog(null, String.format( - I18nUtils.localizedStringForKey("msg_too_many_tiles_msg"), 1000000, totalNrOfOnlineTiles), I18nUtils - .localizedStringForKey("msg_too_many_tiles_title"), JOptionPane.ERROR_MESSAGE); + if (totalNrOfOnlineTiles > 3000000) { // CHANGE: increase the max number of tiles + JOptionPane.showMessageDialog(null, + String.format(I18nUtils.localizedStringForKey("msg_too_many_tiles_msg"), 3000000, // CHANGE: increase the max number of tiles + totalNrOfOnlineTiles), + I18nUtils.localizedStringForKey("msg_too_many_tiles_title"), JOptionPane.ERROR_MESSAGE); return; } try { @@ -188,38 +218,40 @@ public class AtlasThread extends Thread implements DownloadJobListener, AtlasCre return; } - ap.initAtlas(atlas); - ap.setVisible(true); + atlasProgress.initAtlas(atlas); + atlasProgress.setVisible(true); Settings s = Settings.getInstance(); - downloadJobDispatcher = new JobDispatcher(s.downloadThreadCount, pauseResumeHandler, ap); - try { + try (JobDispatcher downloadJobDispatcher = new JobDispatcher(this, s.downloadThreadCount, pauseResumeHandler, + atlasProgress)) { + this.downloadJobDispatcher = downloadJobDispatcher; for (LayerInterface layer : atlas) { atlasCreator.initLayerCreation(layer); for (MapInterface map : layer) { try { - while (!createMap(map)) - ; + while (!createMap(map)) { + } } catch (InterruptedException e) { throw e; // User has aborted } catch (MapDownloadSkippedException e) { // Do nothing and continue with next map } catch (Exception e) { - log.error("", e); - String[] options = { I18nUtils.localizedStringForKey("Continue"), + LOG.error(e.getMessage(), e); + String[] options = {I18nUtils.localizedStringForKey("Continue"), I18nUtils.localizedStringForKey("Abort"), - I18nUtils.localizedStringForKey("dlg_download_show_error_report") }; + I18nUtils.localizedStringForKey("dlg_download_show_error_report")}; int a = JOptionPane.showOptionDialog(null, I18nUtils.localizedStringForKey("dlg_download_erro_head") + e.getMessage() + "\n[" + e.getClass().getSimpleName() + "]\n\n", I18nUtils.localizedStringForKey("Error"), 0, JOptionPane.ERROR_MESSAGE, null, options, options[0]); switch (a) { - case 2: - GUIExceptionHandler.processException(e); - case 1: - throw new InterruptedException(); + case 2 : // show error report + GUIExceptionHandler.processException(e); + case 1 : // Abort + throw new InterruptedException(); + default : // Continue } } } @@ -233,21 +265,22 @@ public class AtlasThread extends Thread implements DownloadJobListener, AtlasCre throw e; } finally { // In case of an abort: Stop create new download jobs - if (djp != null) - djp.cancel(); - downloadJobDispatcher.terminateAllWorkerThreads(); - if (!atlasCreator.isAborted()) + if (downloadJobProducerThread != null) { + downloadJobProducerThread.cancel(); + } + this.downloadJobDispatcher = null; + if (!atlasCreator.isAborted()) { atlasCreator.finishAtlasCreation(); - ap.atlasCreationFinished(); + } + atlasProgress.atlasCreationFinished(); } } /** - * * @param map - * @return true if map creation process was finished and false if something went wrong and the user decided to retry - * map download + * @return true if map creation process was finished and false if something went + * wrong and the user decided to retry map download * @throws Exception */ public boolean createMap(MapInterface map) throws Exception { @@ -258,119 +291,131 @@ public class AtlasThread extends Thread implements DownloadJobListener, AtlasCre jobsRetryError = 0; jobsPermanentError = 0; - ap.initMapDownload(map); - if (currentThread().isInterrupted()) + atlasProgress.initMapDownload(map); + + if (map.getMapSource() instanceof InitializableMapSource) { + ((InitializableMapSource) map.getMapSource()).initialize(); + } + + if (currentThread().isInterrupted()) { throw new InterruptedException(); + } // Prepare the tile store directory // ts.prepareTileStore(map.getMapSource()); /*** - * In this section of code below, tiles for Atlas is being downloaded and saved in the temporary layer tar file - * in the system temp directory. + * In this section of code below, tiles for Atlas is being downloaded and saved + * in the temporary layer tar file in the system temp directory. **/ int zoom = map.getZoom(); final int tileCount = (int) map.calculateTilesToDownload(); - ap.setZoomLevel(zoom); + atlasProgress.setZoomLevel(zoom); try { - tileArchive = null; TileProvider mapTileProvider; if (!(map.getMapSource() instanceof FileBasedMapSource)) { - // For online maps we download the tiles first and then start creating the map if + // For online maps we download the tiles first and then start creating the map + // if // we are sure we got all tiles if (!AtlasOutputFormat.TILESTORE.equals(atlas.getOutputFormat())) { String tempSuffix = "MOBAC_" + atlas.getName() + "_" + zoom + "_"; File tileArchiveFile = File.createTempFile(tempSuffix, ".tar", DirectoryManager.tempDir); // If something goes wrong the temp file only persists until the VM exits tileArchiveFile.deleteOnExit(); - log.debug("Writing downloaded tiles to " + tileArchiveFile.getPath()); + LOG.debug("Writing downloaded tiles to {}", tileArchiveFile.getPath()); tileArchive = new TarIndexedArchive(tileArchiveFile, tileCount); - } else - log.debug("Downloading to tile store only"); + } else { + LOG.debug("Downloading to tile store only"); + } - djp = new DownloadJobProducerThread(this, downloadJobDispatcher, tileArchive, (DownloadableElement) map); + downloadJobProducerThread = new DownloadJobProducerThread(this, downloadJobDispatcher, tileArchive, + (DownloadableElement) map); boolean failedMessageAnswered = false; - while (djp.isAlive() || (downloadJobDispatcher.getWaitingJobCount() > 0) + while (downloadJobProducerThread.isAlive() || (downloadJobDispatcher.getWaitingJobCount() > 0) || downloadJobDispatcher.isAtLeastOneWorkerActive()) { Thread.sleep(500); - if (!failedMessageAnswered && (jobsRetryError > 50) && !ap.ignoreDownloadErrors()) { + if (!failedMessageAnswered && (jobsRetryError > 50) && !atlasProgress.ignoreDownloadErrors()) { pauseResumeHandler.pause(); - String[] answers = new String[] { I18nUtils.localizedStringForKey("Continue"), + String[] answers = new String[]{I18nUtils.localizedStringForKey("Continue"), I18nUtils.localizedStringForKey("Retry"), I18nUtils.localizedStringForKey("Skip"), - I18nUtils.localizedStringForKey("Abort") }; - int answer = JOptionPane.showOptionDialog(ap, + I18nUtils.localizedStringForKey("Abort")}; + int answer = JOptionPane.showOptionDialog(atlasProgress, I18nUtils.localizedStringForKey("dlg_download_errors_todo_msg"), I18nUtils.localizedStringForKey("dlg_download_errors_todo"), 0, JOptionPane.QUESTION_MESSAGE, null, answers, answers[0]); failedMessageAnswered = true; switch (answer) { - case 0: // Continue - pauseResumeHandler.resume(); - break; - case 1: // Retry - djp.cancel(); - djp = null; - downloadJobDispatcher.cancelOutstandingJobs(); - return false; - case 2: // Skip - downloadJobDispatcher.cancelOutstandingJobs(); - throw new MapDownloadSkippedException(); - default: // Abort or close dialog - downloadJobDispatcher.cancelOutstandingJobs(); - downloadJobDispatcher.terminateAllWorkerThreads(); - throw new InterruptedException(); + case 0 : // Continue + pauseResumeHandler.resume(); + break; + case 1 : // Retry + downloadJobProducerThread.cancel(); + downloadJobProducerThread = null; + downloadJobDispatcher.cancelOutstandingJobs(); + return false; + case 2 : // Skip + downloadJobDispatcher.cancelOutstandingJobs(); + throw new MapDownloadSkippedException(); + default : // Abort or close dialog + downloadJobDispatcher.cancelOutstandingJobs(); + downloadJobDispatcher.terminateAllWorkerThreads(); + throw new InterruptedException(); } } } - djp = null; - log.debug("All download jobs has been completed!"); + downloadJobProducerThread = null; + LOG.debug("All download jobs has been completed!"); if (tileArchive != null) { tileArchive.writeEndofArchive(); tileArchive.close(); tileIndex = tileArchive.getTarIndex(); - if (tileIndex.size() < tileCount && !ap.ignoreDownloadErrors()) { + if (tileIndex.size() < tileCount && !atlasProgress.ignoreDownloadErrors()) { int missing = tileCount - tileIndex.size(); - log.debug("Expected tile count: " + tileCount + " downloaded tile count: " + tileIndex.size() - + " missing: " + missing); - int answer = JOptionPane.showConfirmDialog(ap, String.format( - I18nUtils.localizedStringForKey("dlg_download_errors_missing_tile_msg"), missing), + LOG.debug("Expected tile count: {} downloaded tile count: {} missing: {}", tileCount, + tileIndex.size(), missing); + int answer = JOptionPane.showConfirmDialog(atlasProgress, + String.format(I18nUtils.localizedStringForKey("dlg_download_errors_missing_tile_msg"), + missing), I18nUtils.localizedStringForKey("dlg_download_errors_missing_tile"), JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE); - if (answer != JOptionPane.YES_OPTION) + if (answer != JOptionPane.YES_OPTION) { throw new InterruptedException(); + } } } downloadJobDispatcher.cancelOutstandingJobs(); - log.debug("Starting to create atlas from downloaded tiles"); + LOG.debug("Starting to create atlas from downloaded tiles"); mapTileProvider = new DownloadedTileProvider(tileIndex, map); } else { - // We don't need to download anything. Everything is already stored locally therefore we can just use it + // We don't need to download anything. Everything is already stored locally + // therefore we can just use it mapTileProvider = new FilteredMapSourceProvider(map, LoadMethod.DEFAULT); } atlasCreator.initializeMap(map, mapTileProvider); atlasCreator.createMap(); } catch (Error e) { - log.error("Error in createMap: " + e.getMessage(), e); + LOG.error("Error in createMap: {}", e.getMessage(), e); throw e; } finally { - if (tileIndex != null) + if (tileIndex != null) { tileIndex.closeAndDelete(); - else if (tileArchive != null) + } else if (tileArchive != null) { tileArchive.delete(); + } } return true; } public void pauseResumeAtlasCreation() { if (pauseResumeHandler.isPaused()) { - log.debug("Atlas creation resumed"); + LOG.debug("Atlas creation resumed"); pauseResumeHandler.resume(); } else { - log.debug("Atlas creation paused"); + LOG.debug("Atlas creation paused"); pauseResumeHandler.pause(); } } @@ -388,15 +433,18 @@ public class AtlasThread extends Thread implements DownloadJobListener, AtlasCre */ public void abortAtlasCreation() { try { - DownloadJobProducerThread djp_ = djp; - if (djp_ != null) + DownloadJobProducerThread djp_ = downloadJobProducerThread; + if (djp_ != null) { djp_.cancel(); - if (downloadJobDispatcher != null) - downloadJobDispatcher.terminateAllWorkerThreads(); + } + JobDispatcher dispatcher = downloadJobDispatcher; + if (dispatcher != null) { + dispatcher.terminateAllWorkerThreads(); + } pauseResumeHandler.resume(); this.interrupt(); } catch (Exception e) { - log.error("Exception thrown in stopDownload()" + e.getMessage()); + LOG.error("Exception thrown in stopDownload(): {}", e.getMessage()); } } @@ -410,27 +458,28 @@ public class AtlasThread extends Thread implements DownloadJobListener, AtlasCre public void jobFinishedSuccessfully(int bytesDownloaded) { synchronized (this) { - ap.incMapDownloadProgress(); + atlasProgress.incMapDownloadProgress(); activeDownloads--; jobsCompleted++; } - ap.updateGUI(); + atlasProgress.updateGUI(); } public void jobFinishedWithError(boolean retry) { synchronized (this) { activeDownloads--; - if (retry) + if (retry) { jobsRetryError++; - else { + } else { jobsPermanentError++; - ap.incMapDownloadProgress(); + atlasProgress.incMapDownloadProgress(); } } - if (!ap.ignoreDownloadErrors()) + if (!atlasProgress.ignoreDownloadErrors()) { Toolkit.getDefaultToolkit().beep(); - ap.setErrorCounter(jobsRetryError, jobsPermanentError); - ap.updateGUI(); + } + atlasProgress.setErrorCounter(jobsRetryError, jobsPermanentError); + atlasProgress.updateGUI(); } public int getMaxDownloadRetries() { @@ -438,7 +487,7 @@ public class AtlasThread extends Thread implements DownloadJobListener, AtlasCre } public AtlasProgress getAtlasProgress() { - return ap; + return atlasProgress; } public File getCustomAtlasDir() { @@ -453,4 +502,8 @@ public class AtlasThread extends Thread implements DownloadJobListener, AtlasCre this.quitMobacAfterAtlasCreation = quitMobacAfterAtlasCreation; } + @Override + public boolean isMapPreviewThread() { + return false; + } } diff --git a/src/main/java/mobac/program/DirectoryManager.java b/mobac/src/main/java/mobac/program/DirectoryManager.java similarity index 65% rename from src/main/java/mobac/program/DirectoryManager.java rename to mobac/src/main/java/mobac/program/DirectoryManager.java index f5a1bfa..6060eeb 100644 --- a/src/main/java/mobac/program/DirectoryManager.java +++ b/mobac/src/main/java/mobac/program/DirectoryManager.java @@ -1,32 +1,34 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program; +import mobac.utilities.Utilities; + +import javax.swing.JOptionPane; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.swing.JOptionPane; - -import mobac.utilities.Utilities; - /** * Provides the common directories used within Mobile Atlas Creator: *
        @@ -36,7 +38,6 @@ import mobac.utilities.Utilities; *
      • user settings directory
      • *
      • temporary directory
      • *
      - * */ public class DirectoryManager { @@ -44,7 +45,7 @@ public class DirectoryManager { public static final File programDir; public static final File userHomeDir; public static final File tempDir; - public static final File userAppDataDir; + public static final File mobacUserAppDataDir; public static final File userSettingsDir; public static final File mapSourcesDir; @@ -60,7 +61,7 @@ public class DirectoryManager { programDir = getProgramDir(); loadDirectoriesIni(); - userAppDataDir = getUserAppDataDir(); + mobacUserAppDataDir = getMobacUserAppDataDir(); tempDir = applyDirConfig("mobac.tmpdir", new File(System.getProperty("java.io.tmpdir"))); mapSourcesDir = applyDirConfig("mobac.mapsourcesdir", new File(programDir, "mapsources")); @@ -71,8 +72,9 @@ public class DirectoryManager { } private static File applyDirConfig(String propertyName, File defaultDir) { - if (dirConfig == null) + if (dirConfig == null) { return defaultDir; + } try { final String dirCfg = dirConfig.getProperty(propertyName); if (dirCfg == null) { @@ -82,9 +84,11 @@ public class DirectoryManager { } } catch (Exception e) { Logging.LOG.error("Error reading directory configuration: " + e.getMessage(), e); - JOptionPane.showMessageDialog(null, "

      Failed to load directory.ini - entry \"" + propertyName - + "\":

      " + e.getMessage() + "

      ", "Faile do load directory.ini", - JOptionPane.ERROR_MESSAGE); + JOptionPane + .showMessageDialog(null, + "

      Failed to load directory.ini - entry \"" + propertyName + "\":

      " + + e.getMessage() + "

      ", + "Faile do load directory.ini", JOptionPane.ERROR_MESSAGE); return defaultDir; } } @@ -93,7 +97,7 @@ public class DirectoryManager { * Modified version of * http://stackoverflow.com/questions/2090647/evaluation-of-environment-variables-in-command-run- * by-javas-runtime-exec - * + * * @param cmd * @return */ @@ -104,32 +108,34 @@ public class DirectoryManager { final StringBuffer sb = new StringBuffer(cmd.length()); int lastMatchEnd = 0; while (m.find()) { - sb.append(cmd.substring(lastMatchEnd, m.start())); + sb.append(cmd, lastMatchEnd, m.start()); final String envVar = m.group(1); String envVal = System.getenv(envVar); if (envVal == null) { File defPath = null; - if ("mobac-prog".equalsIgnoreCase(envVar)) + if ("mobac-prog".equalsIgnoreCase(envVar)) { defPath = programDir; - else if ("home".equalsIgnoreCase(envVar)) + } else if ("home".equalsIgnoreCase(envVar)) { defPath = userHomeDir; - else if ("XDG_CONFIG_HOME".equalsIgnoreCase(envVar)) + } else if ("XDG_CONFIG_HOME".equalsIgnoreCase(envVar)) { defPath = new File(userHomeDir, ".config"); - else if ("XDG_CACHE_HOME".equalsIgnoreCase(envVar)) + } else if ("XDG_CACHE_HOME".equalsIgnoreCase(envVar)) { defPath = new File(userHomeDir, ".cache"); - else if ("XDG_DATA_HOME".equalsIgnoreCase(envVar)) { + } else if ("XDG_DATA_HOME".equalsIgnoreCase(envVar)) { File localDataDir = new File(userHomeDir, ".local"); defPath = new File(localDataDir, "share"); } - if (defPath != null) + if (defPath != null) { envVal = defPath.getAbsolutePath(); + } } - if (envVal == null) - sb.append(cmd.substring(m.start(), m.end())); - else + if (envVal == null) { + sb.append(cmd, m.start(), m.end()); + } else { sb.append(envVal); + } lastMatchEnd = m.end(); } sb.append(cmd.substring(lastMatchEnd)); @@ -138,78 +144,96 @@ public class DirectoryManager { } public static void initialize() { - if (currentDir == null || userAppDataDir == null || tempDir == null || programDir == null) + if (currentDir == null || mobacUserAppDataDir == null || tempDir == null || programDir == null) { throw new RuntimeException("DirectoryManager failed"); + } } private static void loadDirectoriesIni() { File dirIniFile = new File(programDir, "directories.ini"); - if (!dirIniFile.isFile()) + if (!dirIniFile.isFile()) { return; + } dirConfig = new Properties(); - FileInputStream in = null; - try { - in = new FileInputStream(dirIniFile); + try (FileInputStream in = new FileInputStream(dirIniFile)) { dirConfig.load(in); } catch (IOException e) { System.err.println("Failed to load " + dirIniFile.getName()); e.printStackTrace(); - } finally { - Utilities.closeStream(in); } } /** * Returns the directory from which this java program is executed - * + * * @return */ private static File getProgramDir() { - File f = null; + Path path = null; try { - f = Utilities.getClassLocation(DirectoryManager.class); + path = Utilities.getClassLocation(DirectoryManager.class); } catch (Exception e) { - System.err.println(e.getMessage()); + System.err.println("Unable to get program directory: " + e.getMessage()); return currentDir; } - if ("bin".equals(f.getName())) // remove the bin dir -> this usually - // happens only in a development environment - return f.getParentFile(); - else - return f; + if (Files.isRegularFile(path)) { + // Class is executed from inside of a JAR + String pathStr = path.getParent().toString(); + String intellijMobacRunPath = Paths.get("mobac", "mobac", "build", "libs").toString(); + if (pathStr.endsWith(intellijMobacRunPath)) { + return path.getParent().getParent().getParent().getParent().toFile(); + } + return path.getParent().toFile(); + } + if (Files.isDirectory(path)) { + // The compiled classes are in a directory structure, thus we are running from + // an Java development IDE + // We try to find the project root dir by searching for the gradlew script + Path p = path; + while (p != null) { + if (Files.isRegularFile(p.resolve("gradlew"))) { + // project root dir found; + return p.toFile(); + } + p = p.getParent(); + } + } + System.err.println("Unable to get program directory"); + return currentDir; } /** - * Returns the directory where Mobile Atlas Creator saves it's application settings. - * + * Returns the directory where Mobile Atlas Creator saves it's application + * settings. + *

      * Examples: *

        - *
      • English Windows XP:
        - * C:\Document and Settings\%username%\Application Data\Mobile Atlas Creator - *
      • Vista:
        - * C:\Users\%username%\Application Data\Mobile Atlas Creator + *
      • Windows 10:
        + * C:\Users\%username%\AppData\Roaming\Mobile Atlas Creator *
      • Linux:
        * /home/$username$/.mobac
      • *
      - * + * * @return */ - private static File getUserAppDataDir() { + private static File getMobacUserAppDataDir() { String appData = System.getenv("APPDATA"); if (appData != null) { File appDataDir = new File(appData); if (appDataDir.isDirectory()) { File mobacDataDir = new File(appData, "Mobile Atlas Creator"); - if (mobacDataDir.isDirectory() || mobacDataDir.mkdir()) + if (mobacDataDir.isDirectory() || mobacDataDir.mkdir()) { return mobacDataDir; - else + } else { throw new RuntimeException("Unable to create directory \"" + mobacDataDir.getAbsolutePath() + "\""); + } } } File userDir = new File(System.getProperty("user.home")); File mobacUserDir = new File(userDir, ".mobac"); - if (!mobacUserDir.exists() && !mobacUserDir.mkdir()) + if (!mobacUserDir.exists() && !mobacUserDir.mkdir()) { throw new RuntimeException("Unable to create directory \"" + mobacUserDir.getAbsolutePath() + "\""); + } return mobacUserDir; } } diff --git a/src/main/java/mobac/program/EnvironmentSetup.java b/mobac/src/main/java/mobac/program/EnvironmentSetup.java similarity index 77% rename from src/main/java/mobac/program/EnvironmentSetup.java rename to mobac/src/main/java/mobac/program/EnvironmentSetup.java index f57658c..82db6f0 100644 --- a/src/main/java/mobac/program/EnvironmentSetup.java +++ b/mobac/src/main/java/mobac/program/EnvironmentSetup.java @@ -1,28 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program; -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.util.Locale; - -import javax.swing.JOptionPane; - import mobac.mapsources.MapSourcesManager; import mobac.program.interfaces.MapSource; import mobac.program.model.Atlas; @@ -35,26 +28,31 @@ import mobac.utilities.I18nUtils; import mobac.utilities.Utilities; import mobac.utilities.file.FileExtFilter; import mobac.utilities.file.NamePatternFileFilter; - import org.apache.commons.io.FileUtils; -import org.apache.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.swing.JOptionPane; +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.util.Locale; /** - * Creates the necessary files on first time Mobile Atlas Creator is started or tries to update the environment if the - * version has changed. + * Creates the necessary files on first time Mobile Atlas Creator is started or + * tries to update the environment if the version has changed. */ public class EnvironmentSetup { + private static final Logger log = LoggerFactory.getLogger(EnvironmentSetup.class); private static boolean FIRST_START = false; - public static Logger log = Logger.getLogger(EnvironmentSetup.class); - public static void checkMemory() { Runtime r = Runtime.getRuntime(); long maxHeap = r.maxMemory(); String heapMBFormatted = String.format(Locale.ENGLISH, "%3.2f MiB", maxHeap / 1048576d); - log.info("Total available memory to MOBAC: " + heapMBFormatted); - if (maxHeap < 200000000) { + log.info("Total available memory to MOBAC: {}", heapMBFormatted); + if (maxHeap < 400000000) { String msg = String.format(I18nUtils.localizedStringForKey("msg_environment_lack_memory"), heapMBFormatted); JOptionPane.showMessageDialog(null, msg, I18nUtils.localizedStringForKey("msg_environment_lack_memory_title"), JOptionPane.WARNING_MESSAGE); @@ -72,21 +70,24 @@ public class EnvironmentSetup { } /** - * In case the mapsources directory has been moved by configuration (directories.ini or settings.xml) we - * need to copy the existing map packs into the configured directory + * In case the mapsources directory has been moved by configuration + * (directories.ini or settings.xml) we need to copy the existing map packs into + * the configured directory */ public static void copyMapPacks() { File userMapSourcesDir = Settings.getInstance().getMapSourcesDirectory(); File progMapSourcesDir = new File(DirectoryManager.programDir, "mapsources"); - if (userMapSourcesDir.equals(progMapSourcesDir)) + if (userMapSourcesDir.equals(progMapSourcesDir)) { return; // no user specific directory configured - if (userMapSourcesDir.isDirectory()) + } + if (userMapSourcesDir.isDirectory()) { return; // directory already exists - map packs should have been already copied + } try { Utilities.mkDirs(userMapSourcesDir); FileUtils.copyDirectory(progMapSourcesDir, userMapSourcesDir, new FileExtFilter(".jar")); } catch (IOException e) { - log.error(e); + log.error(e.getMessage(), e); JOptionPane.showMessageDialog(null, I18nUtils.localizedStringForKey("msg_environment_error_init_mapsrc_dir") + e.getMessage(), I18nUtils.localizedStringForKey("Error"), JOptionPane.ERROR_MESSAGE); @@ -95,8 +96,8 @@ public class EnvironmentSetup { } /** - * Note: This method has be be called before {@link Settings#loadOrQuit()}. Therefore no localization is available at - * this point. + * Note: This method has be be called before {@link Settings#loadOrQuit()}. + * Therefore no localization is available at this point. */ public static void checkFileSetup() { checkDirectory(DirectoryManager.userSettingsDir, "user settings", true); @@ -109,11 +110,13 @@ public class EnvironmentSetup { Settings.save(); } catch (Exception e) { log.error("Error while creating settings.xml: " + e.getMessage(), e); - String[] options = { "Exit", "Show error report" }; + String[] options = {"Exit", "Show error report"}; int a = JOptionPane.showOptionDialog(null, "Could not create file settings.xml - program will exit.", "Error", 0, JOptionPane.ERROR_MESSAGE, null, options, options[0]); - if (a == 1) + if (a == 1) { + // SHow error report GUIExceptionHandler.showExceptionDialog(e); + } System.exit(1); } } @@ -125,10 +128,12 @@ public class EnvironmentSetup { } catch (IOException e) { GUIExceptionHandler.processFatalExceptionSimpleDialog( String.format(I18nUtils.localizedStringForKey("msg_environment_error_create_dir"), dirName, - dir.getAbsolutePath()), e); + dir.getAbsolutePath()), + e); } - if (!checkIsWriteable) + if (!checkIsWriteable) { return; + } try { // test if we can write into that directory File testFile = File.createTempFile("MOBAC", "", dir); @@ -138,25 +143,27 @@ public class EnvironmentSetup { } catch (IOException e) { GUIExceptionHandler.processFatalExceptionSimpleDialog( String.format(I18nUtils.localizedStringForKey("msg_environment_error_write_file"), dirName, - dir.getAbsolutePath()), e); + dir.getAbsolutePath()), + e); } } public static void createDefaultAtlases() { - if (!FIRST_START) + if (!FIRST_START) { return; - // TODO:MP change sample to Chinese - Profile p = new Profile("Google Maps New York"); + } Atlas atlas = Atlas.newInstance(); try { EastNorthCoordinate max = new EastNorthCoordinate(40.97264, -74.142609); EastNorthCoordinate min = new EastNorthCoordinate(40.541982, -73.699036); - Layer layer = new Layer(atlas, "GM New York"); - MapSource ms = MapSourcesManager.getInstance().getSourceByName("Mapnik"); - if (ms == null) + Layer layer = new Layer(atlas, "Sample New York"); + MapSource ms = MapSourcesManager.getInstance().getDefaultMapSource(); + Profile p = new Profile(ms.getName() + " New York"); + if (ms == null) { return; - layer.addMapsAutocut("GM New York 16", ms, max, min, 16, null, 32000); - layer.addMapsAutocut("GM New York 14", ms, max, min, 14, null, 32000); + } + layer.addMapsAutocut("New York 16", ms, max, min, 16, null, 32000); + layer.addMapsAutocut("New York 14", ms, max, min, 14, null, 32000); atlas.addLayer(layer); p.save(atlas); } catch (Exception e) { diff --git a/src/main/java/mobac/program/JobDispatcher.java b/mobac/src/main/java/mobac/program/JobDispatcher.java similarity index 67% rename from src/main/java/mobac/program/JobDispatcher.java rename to mobac/src/main/java/mobac/program/JobDispatcher.java index fd44019..a842e94 100644 --- a/src/main/java/mobac/program/JobDispatcher.java +++ b/mobac/src/main/java/mobac/program/JobDispatcher.java @@ -1,67 +1,67 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program; +import mobac.exceptions.StopAllDownloadsException; +import mobac.program.interfaces.MapSourceListener; +import mobac.program.tilestore.berkeleydb.DelayedInterruptThread; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.FileNotFoundException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -import mobac.exceptions.StopAllDownloadsException; -import mobac.program.interfaces.MapSourceListener; -import mobac.program.tilestore.berkeleydb.DelayedInterruptThread; - -import org.apache.log4j.Logger; - /** - * Controls the worker threads that are downloading the map tiles in parallel. Additionally the job queue containing the - * unprocessed tile download jobs can be accessed via this class. + * Controls the worker threads that are downloading the map tiles in parallel. + * Additionally, the job queue containing the unprocessed tile download jobs can + * be accessed via this class. */ -public class JobDispatcher { +public class JobDispatcher implements AutoCloseable { - private static Logger log = Logger.getLogger(JobDispatcher.class); + private static final Logger LOG = LoggerFactory.getLogger(JobDispatcher.class); + protected final AtlasThread atlasThread; + protected final PauseResumeHandler pauseResumeHandler; + protected final MapSourceListener mapSourceListener; + protected final WorkerThread[] workers; + protected final BlockingQueue jobQueue = new LinkedBlockingQueue<>(); protected int maxJobsInQueue = 100; protected int minJobsInQueue = 50; - protected WorkerThread[] workers; - - protected PauseResumeHandler pauseResumeHandler; - - protected MapSourceListener mapSourceListener; - - protected BlockingQueue jobQueue = new LinkedBlockingQueue(); - - public JobDispatcher(int threadCount, PauseResumeHandler pauseResumeHandler, MapSourceListener mapSourceListener) { + public JobDispatcher(AtlasThread atlasThread, int threadCount, PauseResumeHandler pauseResumeHandler, + MapSourceListener mapSourceListener) { + this.atlasThread = atlasThread; this.pauseResumeHandler = pauseResumeHandler; this.mapSourceListener = mapSourceListener; workers = new WorkerThread[threadCount]; - for (int i = 0; i < threadCount; i++) + for (int i = 0; i < threadCount; i++) { workers[i] = new WorkerThread(i); + } } @Override - protected void finalize() throws Throwable { + public void close() { terminateAllWorkerThreads(); - super.finalize(); } public void terminateAllWorkerThreads() { cancelOutstandingJobs(); - log.trace("Killing all worker threads"); + LOG.trace("Killing all worker threads"); for (int i = 0; i < workers.length; i++) { try { WorkerThread w = workers[i]; @@ -81,7 +81,7 @@ public class JobDispatcher { /** * Blocks if more than 100 jobs are already scheduled. - * + * * @param job * @throws InterruptedException */ @@ -100,7 +100,7 @@ public class JobDispatcher { /** * Adds the job to the job-queue and returns. This method will never block! - * + * * @param job */ public void addErrorJob(Job job) { @@ -115,33 +115,34 @@ public class JobDispatcher { return jobQueue.size(); } - public static interface Job { - public void run(JobDispatcher dispatcher) throws Exception; - } - public boolean isAtLeastOneWorkerActive() { for (int i = 0; i < workers.length; i++) { WorkerThread w = workers[i]; if (w != null) { - if ((!w.idle) && (w.getState() != Thread.State.WAITING)) + if ((!w.idle) && (w.getState() != Thread.State.WAITING)) { return true; + } } } - log.debug("All worker threads are idle"); + LOG.debug("All worker threads are idle"); return false; } + public interface Job { + void run(JobDispatcher dispatcher) throws Exception; + } + /** - * Each worker thread takes the first job from the job queue and executes it. If the queue is empty the worker - * blocks, waiting for the next job. + * Each worker thread takes the first job from the job queue and executes it. If + * the queue is empty the worker blocks, waiting for the next job. */ - protected class WorkerThread extends DelayedInterruptThread implements MapSourceListener { + public class WorkerThread extends DelayedInterruptThread implements MapSourceListener { Job job = null; boolean idle = true; - private Logger log = Logger.getLogger(WorkerThread.class); + private final Logger log = LoggerFactory.getLogger(WorkerThread.class); public WorkerThread(int threadNum) { super(String.format("WorkerThread %02d", threadNum)); @@ -168,8 +169,9 @@ public class JobDispatcher { } catch (InterruptedException e) { return; } - if (job == null) + if (job == null) { return; + } try { job.run(JobDispatcher.this); job = null; @@ -177,12 +179,12 @@ public class JobDispatcher { } catch (StopAllDownloadsException e) { JobDispatcher.this.terminateAllWorkerThreads(); JobDispatcher.this.cancelOutstandingJobs(); - log.warn("All downloads has been stoppened: " + e.getMessage()); + log.warn("All downloads has been stoppened: {}", e.getMessage()); return; } catch (FileNotFoundException e) { - log.error("Download failed: " + e.getMessage()); + log.error("Download failed: {}", e.getMessage()); } catch (Exception e) { - log.error("Unknown error occured while executing the job: ", e); + log.error("Unknown error occurred while executing the job: ", e); } catch (OutOfMemoryError e) { log.error("", e); Thread.sleep(5000); @@ -199,6 +201,14 @@ public class JobDispatcher { mapSourceListener.tileLoadedFromCache(size); } + @Override + public void tileDownloadStarted(String tileUrl) { + mapSourceListener.tileDownloadStarted(tileUrl); + } + + public AtlasThread getAtlasThread() { + return JobDispatcher.this.atlasThread; + } } } diff --git a/mobac/src/main/java/mobac/program/Logging.java b/mobac/src/main/java/mobac/program/Logging.java new file mode 100644 index 0000000..c7ec644 --- /dev/null +++ b/mobac/src/main/java/mobac/program/Logging.java @@ -0,0 +1,203 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.LoggerContext; +import ch.qos.logback.classic.encoder.PatternLayoutEncoder; +import ch.qos.logback.classic.filter.ThresholdFilter; +import ch.qos.logback.classic.joran.JoranConfigurator; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.Appender; +import ch.qos.logback.core.FileAppender; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.util.StatusPrinter; +import mobac.StartMOBAC; +import mobac.utilities.GUIExceptionHandler; +import mobac.utilities.OSUtilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.bridge.SLF4JBridgeHandler; + +import java.awt.Desktop; +import java.awt.Desktop.Action; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.TreeMap; +import java.util.logging.LogManager; + +public class Logging { + + public static final Logger LOG = LoggerFactory.getLogger("MAC"); + + public static void configureLogging() { + // We test for the configuration file, if it exists we use it, otherwise + // we keep simple logging to the console (configured by logback.xml in + // src/main/resources) + if (!loadLog4JConfigXml()) { + configureDefaultFileLogging(); + LOG.info("logback.xml not found - enabling default error log to console"); + } + LogManager.getLogManager().reset(); + SLF4JBridgeHandler.install(); + } + + public static boolean loadLog4JConfigXml() { + if (loadLogbackConfigXmlFromDir(DirectoryManager.mobacUserAppDataDir)) { + return true; + } + if (loadLogbackConfigXmlFromDir(DirectoryManager.userSettingsDir)) { + return true; + } + if (loadLogbackConfigXmlFromDir(DirectoryManager.currentDir)) { + return true; + } + return loadLogbackConfigXmlFromDir(DirectoryManager.programDir); + } + + public static void configureDefaultFileLogging() { + Path errorLog = DirectoryManager.mobacUserAppDataDir.toPath().resolve("Mobile Atlas Creator.log"); + createFileLogger(errorLog, Level.INFO); + } + + public static boolean loadLogbackConfigXmlFromDir(File dir) { + Path logbackXml = dir.toPath().resolve("logback.xml"); + if (!Files.isRegularFile(logbackXml)) { + return false; + } + return loadLogbackXml(logbackXml); + } + + public static boolean loadLogbackXml(Path logbackXml) { + LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); + JoranConfigurator configurator = new JoranConfigurator(); + try (InputStream configStream = Files.newInputStream(logbackXml)) { + configurator.setContext(loggerContext); + loggerContext.reset(); + configurator.doConfigure(configStream); + StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext); + Logger logger = LoggerFactory.getLogger("LogSystem"); + logger.info("Logging configured by \"{}\"", logbackXml.toAbsolutePath()); + return true; + } catch (IOException | JoranException e) { + LOG.error("Failed to load logback configuration file {}", logbackXml.toAbsolutePath(), e); + } + return false; + } + + private static FileAppender createFileLogger(Path logFile, Level levelFilter) { + LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory(); + PatternLayoutEncoder patternLayoutEncoder = new PatternLayoutEncoder(); + + patternLayoutEncoder.setPattern("%date %-5level %logger %msg%n"); + patternLayoutEncoder.setContext(loggerContext); + patternLayoutEncoder.start(); + FileAppender fileAppender = new FileAppender<>(); + fileAppender.setFile(logFile.toAbsolutePath().normalize().toString()); + fileAppender.setEncoder(patternLayoutEncoder); + fileAppender.setContext(loggerContext); + fileAppender.setAppend(false); + + if (levelFilter != null) { + ThresholdFilter filter = new ThresholdFilter(); + filter.setContext(loggerContext); + filter.setLevel(levelFilter.toString()); + filter.start(); + fileAppender.addFilter(filter); + } + fileAppender.start(); + + ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory + .getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); + logger.addAppender(fileAppender); + return fileAppender; + } + + /** + * returns the first configured {@link FileAppender} or null. + * + * @return + */ + public static String getLogFile() { + ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory + .getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); + Iterator> it = logger.iteratorForAppenders(); + while (it.hasNext()) { + Appender appender = it.next(); + if (appender instanceof FileAppender) { + FileAppender fileAppender = (FileAppender) appender; + return fileAppender.getFile(); + } + } + return null; + } + + public static void logSystemInfo() { + Logger log = LoggerFactory.getLogger("SysInfo"); + if (log.isInfoEnabled()) { + String n = System.getProperty("line.separator"); + log.info("Version: {}", ProgramInfo.getCompleteTitle()); + log.info("Platform: {} ({})", GUIExceptionHandler.prop("os.name"), GUIExceptionHandler.prop("os.version")); + log.info("Java VM: {} ({})", GUIExceptionHandler.prop("java.vm.name"), + GUIExceptionHandler.prop("java.runtime.version")); + log.info("Available processors: {}", Runtime.getRuntime().availableProcessors()); + log.info("Directories:" /**/ + + n + "currentDir: \t\t" + DirectoryManager.currentDir /**/ + + n + "programDir: \t\t" + DirectoryManager.programDir /**/ + + n + "mapSourcesDir: \t\t" + DirectoryManager.mapSourcesDir /**/ + + n + "tempDir: \t\t" + DirectoryManager.tempDir /**/ + + n + "userHomeDir: \t\t" + DirectoryManager.userHomeDir /**/ + + n + "userSettingsDir: \t" + DirectoryManager.userSettingsDir /**/ + + n + "atlasProfilesDir: \t" + DirectoryManager.atlasProfilesDir /**/ + + n + "mobacUserAppDataDir: \t" + DirectoryManager.mobacUserAppDataDir /**/ + ); + log.info("System console available: {}", (System.console() != null)); + log.info("Startup arguments (count={}):", StartMOBAC.ARGS.length); + for (int i = 0; i < StartMOBAC.ARGS.length; i++) { + log.info("\t{}:{}", i, StartMOBAC.ARGS[i]); + } + } + if (log.isDebugEnabled()) { + log.debug("Detected operating system: {} ({})", OSUtilities.detectOs(), System.getProperty("os.name")); + boolean desktopSupport = Desktop.isDesktopSupported(); + log.debug("Desktop support: {}", desktopSupport); + if (desktopSupport) { + Desktop d = Desktop.getDesktop(); + for (Action a : Action.values()) { + log.debug("Desktop action {} supported: {}", a, d.isSupported(a)); + } + } + } + if (log.isTraceEnabled()) { + Properties props = System.getProperties(); + StringWriter sw = new StringWriter(8192); + sw.write("System properties:\n"); + TreeMap sortedProps = new TreeMap<>(props); + for (Entry entry : sortedProps.entrySet()) { + sw.write(entry.getKey() + " = " + entry.getValue() + "\n"); + } + log.trace(sw.toString()); + } + } +} diff --git a/src/main/java/mobac/program/PauseResumeHandler.java b/mobac/src/main/java/mobac/program/PauseResumeHandler.java similarity index 73% rename from src/main/java/mobac/program/PauseResumeHandler.java rename to mobac/src/main/java/mobac/program/PauseResumeHandler.java index 9e63c2b..a5bdbb8 100644 --- a/src/main/java/mobac/program/PauseResumeHandler.java +++ b/mobac/src/main/java/mobac/program/PauseResumeHandler.java @@ -1,64 +1,66 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program; +import java.util.concurrent.atomic.AtomicBoolean; + /** * Central instance that allows to pause/resume multiple threads at once. Used * in MOBAC for pausing/resuming map tile download and map creation process. */ public class PauseResumeHandler { - protected boolean paused = false; + protected final AtomicBoolean paused = new AtomicBoolean(false); public boolean isPaused() { - return paused; + return paused.get(); } /** * Enters the pause state. */ public void pause() { - paused = true; + paused.set(true); } /** * End the pause state and resumes all waiting threads. */ public void resume() { - paused = false; + paused.set(false); synchronized (this) { this.notifyAll(); } } /** - * If {@link #isPaused()}== true this method will not return - * until {@link #resume()} has been called. Otherwise this method returns - * immediately. - * + * If {@link #isPaused()}== true this method will not return until + * {@link #resume()} has been called. Otherwise this method returns immediately. + * * @throws InterruptedException - * Thrown if the calling {@link Thread} is interrupted while - * waiting for resume + * Thrown if the calling {@link Thread} is interrupted while waiting + * for resume */ public void pauseWait() throws InterruptedException { - if (paused) { + if (paused.get()) { synchronized (this) { - if (paused) + if (paused.get()) { this.wait(); + } } } } diff --git a/src/main/java/mobac/program/ProgramInfo.java b/mobac/src/main/java/mobac/program/ProgramInfo.java similarity index 69% rename from src/main/java/mobac/program/ProgramInfo.java rename to mobac/src/main/java/mobac/program/ProgramInfo.java index f5d48ab..cc40dcb 100644 --- a/src/main/java/mobac/program/ProgramInfo.java +++ b/mobac/src/main/java/mobac/program/ProgramInfo.java @@ -1,34 +1,34 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program; -import java.io.InputStream; -import java.util.Properties; - import mobac.Main; import mobac.utilities.GUIExceptionHandler; import mobac.utilities.Utilities; +import java.io.InputStream; +import java.util.Properties; + public class ProgramInfo { public static String PROG_NAME = "Mobile Atlas Creator"; public static String PROG_NAME_SHORT = "MOBAC"; - private static String VERSION = null; + private static String VERSION = "unknown"; private static String SVN_REVISION = "unknown"; private static String userAgent = ""; @@ -38,44 +38,44 @@ public class ProgramInfo { private static boolean titleHideRevision = false; public static void initialize() { - InputStream propIn = Main.class.getResourceAsStream("mobac.properties"); - try { + + try (InputStream in = Main.class.getResourceAsStream("mobac.properties")) { Properties props = new Properties(); - props.load(propIn); - VERSION = props.getProperty("mobac.version"); + props.load(in); titleHideRevision = Boolean.parseBoolean(props.getProperty("mobac.revision.hide", "false")); System.getProperties().putAll(props); } catch (Exception e) { String msg = "Error reading mobac.properties"; GUIExceptionHandler.processFatalExceptionSimpleDialog(msg, e); - } finally { - Utilities.closeStream(propIn); } - propIn = Main.class.getResourceAsStream("mobac-rev.properties"); - try { - String rev; - if (propIn != null) { + try (InputStream in = Main.class.getResourceAsStream("mobac-rev.properties")) { + boolean versionSet = false; + if (in != null) { Properties props = new Properties(); - props.load(propIn); - rev = props.getProperty("mobac.revision"); - SVN_REVISION = Integer.toString(Utilities.parseSVNRevision(rev)); - } else { - rev = System.getProperty("mobac.revision.fallback"); - SVN_REVISION = Integer.toString(Utilities.parseSVNRevision(rev)) + " exported"; + props.load(in); + String rev = props.getProperty("mobac.revision"); + int svnRev = Utilities.parseSVNRevision(rev); + if (svnRev > 0) { + SVN_REVISION = Integer.toString(svnRev); + versionSet = true; + } + VERSION = props.getProperty("mobac.version", VERSION); + } + if (!versionSet) { + String rev = System.getProperty("mobac.revision.fallback"); + SVN_REVISION = Utilities.parseSVNRevision(rev) + " exported"; } } catch (Exception e) { Logging.LOG.error("Error reading mobac-rev.properties", e); - } finally { - Utilities.closeStream(propIn); } userAgent = PROG_NAME_SHORT + "/" + (getVersion().replaceAll(" ", "_")); } public static String getVersion() { - if (VERSION != null) + if (VERSION != null) { return VERSION; - else - return "UNKNOWN"; + } + return "UNKNOWN"; } public static String getRevisionStr() { @@ -84,21 +84,24 @@ public class ProgramInfo { public static String getVersionTitle() { String title = PROG_NAME; - if (PROG_NAME_SHORT != null) + if (PROG_NAME_SHORT != null) { title += " (" + PROG_NAME_SHORT + ") "; - else + } else { title += " "; + } if (VERSION != null) { title += getVersion(); - } else + } else { title += "unknown version"; + } return title; } public static String getCompleteTitle() { String title = getVersionTitle(); - if (!titleHideRevision) + if (!titleHideRevision) { title += " (" + SVN_REVISION + ")"; + } return title; } diff --git a/src/main/java/mobac/program/annotations/AtlasCreatorName.java b/mobac/src/main/java/mobac/program/annotations/AtlasCreatorName.java similarity index 74% rename from src/main/java/mobac/program/annotations/AtlasCreatorName.java rename to mobac/src/main/java/mobac/program/annotations/AtlasCreatorName.java index 2ec4684..5cb6b92 100644 --- a/src/main/java/mobac/program/annotations/AtlasCreatorName.java +++ b/mobac/src/main/java/mobac/program/annotations/AtlasCreatorName.java @@ -1,32 +1,30 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.annotations; +import mobac.program.atlascreators.AtlasCreator; + import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import mobac.program.atlascreators.AtlasCreator; -import mobac.program.model.TileImageParameters.Name; - /** - * Annotation for {@link AtlasCreator} implementations. The {@link #names()} field holds the parameter names supported - * by the specific atlas format. The full list of available parameters is defined in {@link Name}. + * Annotation for {@link AtlasCreator} implementations. */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) diff --git a/src/main/java/mobac/program/annotations/SupportedParameters.java b/mobac/src/main/java/mobac/program/annotations/SupportedParameters.java similarity index 77% rename from src/main/java/mobac/program/annotations/SupportedParameters.java rename to mobac/src/main/java/mobac/program/annotations/SupportedParameters.java index b2339fa..1e5d48a 100644 --- a/src/main/java/mobac/program/annotations/SupportedParameters.java +++ b/mobac/src/main/java/mobac/program/annotations/SupportedParameters.java @@ -1,38 +1,38 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.annotations; +import mobac.program.atlascreators.AtlasCreator; +import mobac.program.model.TileImageParameters.Name; + import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import mobac.program.atlascreators.AtlasCreator; -import mobac.program.model.TileImageParameters; -import mobac.program.model.TileImageParameters.Name; - /** - * Annotation for {@link AtlasCreator} implementations. The {@link #names()} field holds the parameter names supported - * by the specific atlas format. The full list of available parameters is defined in {@link Name}. + * Annotation for {@link AtlasCreator} implementations. The {@link #names()} + * field holds the parameter names supported by the specific atlas format. The + * full list of available parameters is defined in {@link Name}. */ @Inherited @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface SupportedParameters { - public TileImageParameters.Name[] names(); + Name[] names(); } diff --git a/src/main/java/mobac/program/atlascreators/AFTrack.java b/mobac/src/main/java/mobac/program/atlascreators/AFTrack.java similarity index 76% rename from src/main/java/mobac/program/atlascreators/AFTrack.java rename to mobac/src/main/java/mobac/program/atlascreators/AFTrack.java index 6300f68..f0f6f7a 100644 --- a/src/main/java/mobac/program/atlascreators/AFTrack.java +++ b/mobac/src/main/java/mobac/program/atlascreators/AFTrack.java @@ -1,21 +1,28 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; +import mobac.program.annotations.AtlasCreatorName; +import mobac.program.atlascreators.tileprovider.TileProvider; +import mobac.program.interfaces.LayerInterface; +import mobac.program.interfaces.MapInterface; +import mobac.utilities.Utilities; +import mobac.utilities.stream.ZipStoreOutputStream; + import java.awt.Point; import java.io.ByteArrayOutputStream; import java.io.File; @@ -26,20 +33,13 @@ import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Collections; -import mobac.program.annotations.AtlasCreatorName; -import mobac.program.atlascreators.tileprovider.TileProvider; -import mobac.program.interfaces.LayerInterface; -import mobac.program.interfaces.MapInterface; -import mobac.utilities.Utilities; -import mobac.utilities.stream.ZipStoreOutputStream; - /** * AFTrack OSZ Atlas format */ @AtlasCreatorName("AFTrack (OSZ)") public class AFTrack extends OSMTracker { - private ArrayList zoomLevel = new ArrayList(); + private final ArrayList zoomLevel = new ArrayList<>(); private int maxZoom; private Point min; @@ -67,7 +67,7 @@ public class AFTrack extends OSMTracker { @Override public void initializeMap(MapInterface map, TileProvider mapTileProvider) { super.initializeMap(map, mapTileProvider); - zoomLevel.add(new Integer(map.getZoom())); + zoomLevel.add(map.getZoom()); if (map.getZoom() > maxZoom) { maxZoom = map.getZoom(); min.x = map.getMinTileCoordinate().x / 256; @@ -94,19 +94,20 @@ public class AFTrack extends OSMTracker { } public void finalizeMap() throws IOException { - ByteArrayOutputStream bout = new ByteArrayOutputStream(100); - OutputStreamWriter writer = new OutputStreamWriter(bout); - - Collections.sort(zoomLevel); - for (Integer zoom : zoomLevel) - writer.append(String.format("zoom=%d\r\n", zoom.intValue())); - writer.append(String.format("minx=%d\r\n", min.x)); - writer.append(String.format("maxx=%d\r\n", max.x)); - writer.append(String.format("miny=%d\r\n", min.y)); - writer.append(String.format("maxy=%d\r\n", max.y)); - writer.close(); - zipStream.writeStoredEntry("Manifest.txt", bout.toByteArray()); - Utilities.closeStream(zipStream); + try (ByteArrayOutputStream bout = new ByteArrayOutputStream(100)) { + try (OutputStreamWriter writer = new OutputStreamWriter(bout)) { + Collections.sort(zoomLevel); + for (Integer zoom : zoomLevel) { + writer.append(String.format("zoom=%d\r\n", zoom.intValue())); + } + writer.append(String.format("minx=%d\r\n", min.x)); + writer.append(String.format("maxx=%d\r\n", max.x)); + writer.append(String.format("miny=%d\r\n", min.y)); + writer.append(String.format("maxy=%d\r\n", max.y)); + } + zipStream.writeStoredEntry("Manifest.txt", bout.toByteArray()); + } + Utilities.closeQuietly(zipStream); } } diff --git a/src/main/java/mobac/program/atlascreators/AbstractPlainImage.java b/mobac/src/main/java/mobac/program/atlascreators/AbstractPlainImage.java similarity index 85% rename from src/main/java/mobac/program/atlascreators/AbstractPlainImage.java rename to mobac/src/main/java/mobac/program/atlascreators/AbstractPlainImage.java index e454e65..f2b672a 100644 --- a/src/main/java/mobac/program/atlascreators/AbstractPlainImage.java +++ b/mobac/src/main/java/mobac/program/atlascreators/AbstractPlainImage.java @@ -1,31 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.IOException; - -import javax.imageio.ImageIO; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; @@ -36,13 +26,22 @@ import mobac.program.interfaces.MapSpace; import mobac.program.interfaces.MapSpace.ProjectionCategory; import mobac.utilities.Utilities; +import javax.imageio.ImageIO; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; + public abstract class AbstractPlainImage extends AtlasCreator { @Override public boolean testMapSource(MapSource mapSource) { MapSpace mapSpace = mapSource.getMapSpace(); - return (mapSpace instanceof MercatorPower2MapSpace && ProjectionCategory.SPHERE.equals(mapSpace - .getProjectionCategory())); + return (mapSpace instanceof MercatorPower2MapSpace + && ProjectionCategory.SPHERE.equals(mapSpace.getProjectionCategory())); } @Override @@ -55,9 +54,10 @@ public abstract class AbstractPlainImage extends AtlasCreator { for (MapInterface map : layer) { int w = map.getMaxTileCoordinate().x - map.getMinTileCoordinate().x; int h = map.getMaxTileCoordinate().y - map.getMinTileCoordinate().y; - if (w > maxMapSize || h > maxMapSize) - throw new AtlasTestException("Map size too large for memory (is: " + Math.max(w, h) + " max: " - + maxMapSize + ")", map); + if (w > maxMapSize || h > maxMapSize) { + throw new AtlasTestException( + "Map size too large for memory (is: " + Math.max(w, h) + " max: " + maxMapSize + ")", map); + } } } } @@ -76,7 +76,8 @@ public abstract class AbstractPlainImage extends AtlasCreator { } /** - * @return maximum image height and width. In case an image is larger it will be scaled to fit. + * @return maximum image height and width. In case an image is larger it will be + * scaled to fit. */ protected int getMaxImageSize() { return Integer.MAX_VALUE; @@ -105,26 +106,30 @@ public abstract class AbstractPlainImage extends AtlasCreator { scaleFactor = (double) getMaxImageSize() / (double) len; if (mapWidth != mapHeight) { // Map is not rectangle -> adapt height or width - if (mapWidth > mapHeight) + if (mapWidth > mapHeight) { imageHeight = (int) (scaleFactor * mapHeight); - else + } else { imageWidth = (int) (scaleFactor * mapWidth); + } } } - if (imageHeight < 0 || imageWidth < 0) + if (imageHeight < 0 || imageWidth < 0) { throw new MapCreationException("Invalid map size: (width/height: " + imageWidth + "/" + imageHeight + ")", map); + } long imageSize = 3l * ((long) imageWidth) * ((long) imageHeight); - if (imageSize > Integer.MAX_VALUE) + if (imageSize > Integer.MAX_VALUE) { throw new MapCreationException("Map image too large: (width/height: " + imageWidth + "/" + imageHeight + ") - reduce the map size and try again", map); + } BufferedImage tileImage = Utilities.safeCreateBufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_3BYTE_BGR); Graphics2D graphics = tileImage.createGraphics(); try { if (scaleImage) { graphics.setTransform(AffineTransform.getScaleInstance(scaleFactor, scaleFactor)); - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BILINEAR); } int lineY = 0; for (int y = yMin; y <= yMax; y++) { diff --git a/mobac/src/main/java/mobac/program/atlascreators/AbstractSQLite.java b/mobac/src/main/java/mobac/program/atlascreators/AbstractSQLite.java new file mode 100644 index 0000000..8e9ca12 --- /dev/null +++ b/mobac/src/main/java/mobac/program/atlascreators/AbstractSQLite.java @@ -0,0 +1,151 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.atlascreators; + +import mobac.exceptions.AtlasTestException; +import mobac.exceptions.MapCreationException; +import mobac.program.atlascreators.tileprovider.ConvertedRawTileProvider; +import mobac.program.interfaces.AtlasInterface; +import mobac.program.interfaces.RequiresSQLite; +import mobac.program.model.TileImageParameters; +import mobac.utilities.jdbc.SQLiteLoader; + +import java.io.File; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +public abstract class AbstractSQLite extends AtlasCreator implements RequiresSQLite { + + private static final int MAX_BATCH_SIZE = 1000; + + protected File databaseFile; + + protected Connection conn = null; + protected PreparedStatement prepStmt; + + public AbstractSQLite() { + super(); + SQLiteLoader.loadSQLiteOrShowError(); + } + + protected void openConnection() throws SQLException, IOException { + if (conn == null || conn.isClosed()) { + String url = "jdbc:sqlite:" + databaseFile.getCanonicalPath(); + conn = DriverManager.getConnection(url); + } + } + + @Override + protected void testAtlas() throws AtlasTestException { + super.testAtlas(); + try { + SQLiteLoader.loadSQLite(); + } catch (SQLException e) { + throw new AtlasTestException(SQLiteLoader.getMsgSqliteMissing()); + } + } + + @Override + public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) + throws IOException, AtlasTestException, InterruptedException { + super.startAtlasCreation(atlas, customAtlasDir); + databaseFile = new File(atlasDir, getDatabaseFileName()); + log.debug("SQLite Database file: {}", databaseFile); + } + + @Override + public void abortAtlasCreation() throws IOException { + SQLiteLoader.closeConnection(conn); + conn = null; + super.abortAtlasCreation(); + } + + @Override + public void finishAtlasCreation() throws IOException, InterruptedException { + SQLiteLoader.closeConnection(conn); + conn = null; + super.finishAtlasCreation(); + } + + protected void createTiles() throws InterruptedException, MapCreationException { + int maxMapProgress = 2 * (xMax - xMin + 1) * (yMax - yMin + 1); + atlasProgress.initMapCreation(maxMapProgress); + TileImageParameters param = map.getParameters(); + if (param != null) { + mapDlTileProvider = new ConvertedRawTileProvider(mapDlTileProvider, param.getFormat()); + } + try { + conn.setAutoCommit(false); + int batchTileCount = 0; + int tilesWritten = 0; + Runtime r = Runtime.getRuntime(); + long heapMaxSize = r.maxMemory(); + prepStmt = conn.prepareStatement(getTileInsertSQL()); + for (int x = xMin; x <= xMax; x++) { + for (int y = yMin; y <= yMax; y++) { + checkUserAbort(); + atlasProgress.incMapCreationProgress(); + try { + byte[] sourceTileData = mapDlTileProvider.getTileData(x, y); + if (sourceTileData != null) { + writeTile(x, y, zoom, sourceTileData); + tilesWritten++; + long heapAvailable = heapMaxSize - r.totalMemory() + r.freeMemory(); + + batchTileCount++; + if ((heapAvailable < HEAP_MIN) || (batchTileCount >= MAX_BATCH_SIZE)) { + log.trace("Executing batch containing {} tiles", batchTileCount); + prepStmt.executeBatch(); + prepStmt.clearBatch(); + System.gc(); + conn.commit(); + atlasProgress.incMapCreationProgress(batchTileCount); + batchTileCount = 0; + } + } + } catch (IOException e) { + throw new MapCreationException(map, e); + } + } + } + prepStmt.executeBatch(); + prepStmt.clearBatch(); + prepStmt.close(); + prepStmt = null; + System.gc(); + if (tilesWritten > 0) { + updateTileMetaInfo(); + } + log.trace("Final commit containing {} tiles", batchTileCount); + conn.commit(); + atlasProgress.setMapCreationProgress(maxMapProgress); + } catch (SQLException e) { + throw new MapCreationException(map, e); + } + } + + protected abstract String getTileInsertSQL(); + + protected abstract void writeTile(int x, int y, int z, byte[] tileData) throws SQLException, IOException; + + protected abstract String getDatabaseFileName(); + + protected abstract void updateTileMetaInfo() throws SQLException; +} diff --git a/src/main/java/mobac/program/atlascreators/AlpineQuestMap.java b/mobac/src/main/java/mobac/program/atlascreators/AlpineQuestMap.java similarity index 61% rename from src/main/java/mobac/program/atlascreators/AlpineQuestMap.java rename to mobac/src/main/java/mobac/program/atlascreators/AlpineQuestMap.java index f25c896..1dc33da 100644 --- a/src/main/java/mobac/program/atlascreators/AlpineQuestMap.java +++ b/mobac/src/main/java/mobac/program/atlascreators/AlpineQuestMap.java @@ -1,37 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Insets; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.StringWriter; -import java.text.DecimalFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -import javax.imageio.ImageIO; - import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; import mobac.program.ProgramInfo; @@ -50,16 +34,34 @@ import mobac.program.model.TileImageParameters.Name; import mobac.utilities.I18nUtils; import mobac.utilities.Utilities; import mobac.utilities.stream.ArrayOutputStream; +import org.apache.commons.io.IOUtils; + +import javax.imageio.ImageIO; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.Date; /** * Creates maps using the AlpineQuestMap atlas format (AQM v2 complient). - * - * AQM format pack tiles in a unique file using the FlatPack format. Supports multi-layers, tile resizing. - * + *

      + * AQM format pack tiles in a unique file using the FlatPack format. Supports + * multi-layers, tile resizing. + * * @author Camille */ @AtlasCreatorName("AlpineQuestMap (AQM)") -@SupportedParameters(names = { Name.format, Name.height, Name.width }) +@SupportedParameters(names = {Name.format, Name.height, Name.width}) public class AlpineQuestMap extends AtlasCreator { public static final String AQM_VERSION = "2"; @@ -69,7 +71,8 @@ public class AlpineQuestMap extends AtlasCreator { public static final String AQM_LEVEL_DELIMITER = "@LEVEL"; public static final String AQM_END_DELIMITER = "#END"; - private static final String[] SCALES = new String[] { "1:512 000 000", // 00 + private static final String[] SCALES = new String[]{ // + "1:512 000 000", // 00 "1:256 000 000", // 01 "1:128 000 000", // 02 "1:64 000 000", // 03 @@ -114,7 +117,7 @@ public class AlpineQuestMap extends AtlasCreator { if (layer.getMapCount() > 0) { // create the file - this.filePack = new File(atlasDir + "/" + layer.getName() + ".AQM"); + this.filePack = new File(atlasDir, layer.getName() + ".AQM"); this.packCreator = new FlatPackCreator(filePack); this.lastZoomLevel = -1; @@ -123,13 +126,15 @@ public class AlpineQuestMap extends AtlasCreator { // add level headers for (int i = 0; i < layer.getMapCount(); i++) { - // needed to merge splitted maps due to map size (map split not needed by AQM format) - Insets bounds = new Insets(layer.getMap(i).getMinTileCoordinate().y, layer.getMap(i) - .getMinTileCoordinate().x, layer.getMap(i).getMaxTileCoordinate().y, layer.getMap(i) - .getMaxTileCoordinate().x); + // needed to merge split maps due to map size (map split not needed by AQM + // format) + Insets bounds = new Insets(layer.getMap(i).getMinTileCoordinate().y, + layer.getMap(i).getMinTileCoordinate().x, layer.getMap(i).getMaxTileCoordinate().y, + layer.getMap(i).getMaxTileCoordinate().x); // loops over all maps with the same level and add the bounds - while (((i + 1) < layer.getMapCount()) && (layer.getMap(i).getZoom() == layer.getMap(i + 1).getZoom())) { + while (((i + 1) < layer.getMapCount()) + && (layer.getMap(i).getZoom() == layer.getMap(i + 1).getZoom())) { i++; bounds.top = Math.min(bounds.top, layer.getMap(i).getMinTileCoordinate().y); bounds.left = Math.min(bounds.left, layer.getMap(i).getMinTileCoordinate().x); @@ -154,18 +159,20 @@ public class AlpineQuestMap extends AtlasCreator { @Override public void abortAtlasCreation() throws IOException { - if (packCreator != null) + if (packCreator != null) { packCreator.close(); + } packCreator = null; - if (filePack != null) + if (filePack != null) { Utilities.deleteFile(filePack); + } filePack = null; super.abortAtlasCreation(); } - private final void addMapHeader(final String strID, final String strName) throws IOException { + private void addMapHeader(final String strID, final String strName) throws IOException { // version of the AQM format (internal use) final String strVersion = AQM_VERSION; @@ -178,23 +185,25 @@ public class AlpineQuestMap extends AtlasCreator { // name of the person that created the map (displayed to user) final String strCreator = ""; - StringWriter w = new StringWriter(); - w.write("[map]\n"); - w.write("id = " + strID + "\n"); - w.write("name = " + strName + "\n"); - w.write("version = " + strVersion + "\n"); - w.write("date = " + strDate + "\n"); - w.write("creator = " + strCreator + "\n"); - w.write("software = " + strSoftware + "\n"); - w.write("\n"); - w.flush(); - w.close(); + String headerStr; + try (StringWriter w = new StringWriter()) { + w.write("[map]\n"); + w.write("id = " + strID + "\n"); + w.write("name = " + strName + "\n"); + w.write("version = " + strVersion + "\n"); + w.write("date = " + strDate + "\n"); + w.write("creator = " + strCreator + "\n"); + w.write("software = " + strSoftware + "\n"); + w.write("\n"); + w.flush(); + headerStr = w.getBuffer().toString(); + } // add the metadata file into map - packCreator.add(w.getBuffer().toString().getBytes(), AQM_HEADER); + packCreator.add(headerStr.getBytes(StandardCharsets.ISO_8859_1), AQM_HEADER); } - private final void addLevelHeader(final MapInterface map, final Insets bounds) throws IOException { + private void addLevelHeader(final MapInterface map, final Insets bounds) throws IOException { final int tileSize = map.getMapSource().getMapSpace().getTileSize(); final int xMin = bounds.left / tileSize; final int xMax = bounds.right / tileSize; @@ -206,13 +215,15 @@ public class AlpineQuestMap extends AtlasCreator { // name of this specific map (displayed to user) String strName = map.getLayer().getName(); - if (strName == null || strName.length() == 0) + if (strName == null || strName.length() == 0) { strName = I18nUtils.localizedStringForKey("Unnamed"); + } // scale of the map (displayed to user) String strScale = ""; - if (map.getZoom() >= 0 && map.getZoom() < SCALES.length) + if (map.getZoom() >= 0 && map.getZoom() < SCALES.length) { strScale = SCALES[map.getZoom()]; + } // source of the map data (displayed to user) final String strDataSource = map.getMapSource().toString(); @@ -224,17 +235,21 @@ public class AlpineQuestMap extends AtlasCreator { final String strProjection = "mercator"; String strGeoid = ""; - if (ProjectionCategory.SPHERE.equals(map.getMapSource().getMapSpace().getProjectionCategory())) + ProjectionCategory projectionCategory = map.getMapSource().getMapSpace().getProjectionCategory(); + if (ProjectionCategory.SPHERE.equals(projectionCategory)) { strGeoid = "sphere"; - else if (ProjectionCategory.ELLIPSOID.equals(map.getMapSource().getMapSpace().getProjectionCategory())) + } else if (ProjectionCategory.ELLIPSOID.equals(projectionCategory)) { strGeoid = "wgs84"; + } else { + throw new RuntimeException("Unsupported projection category: " + projectionCategory); + } // number of tiles (internal use) final long nbTotalTiles = (256 * Math.round(Math.pow(2, map.getZoom()))) / tileSize; // check resize or resample parameters - String strImageFormat = null; - Dimension tilesSize = null; + String strImageFormat; + Dimension tilesSize; if (map.getParameters() != null) { strImageFormat = map.getParameters().getFormat().getFileExt(); @@ -244,45 +259,49 @@ public class AlpineQuestMap extends AtlasCreator { tilesSize = map.getTileSize(); } - if (strImageFormat != null) + if (strImageFormat != null) { strImageFormat = strImageFormat.toUpperCase(); + } // write metadata - StringWriter w = new StringWriter(); - w.write("[level]\n"); - w.write("id = " + strID + "\n"); - w.write("name = " + strName + "\n"); - w.write("scale = " + strScale + "\n"); - w.write("datasource = " + strDataSource + "\n"); - w.write("copyright = " + strCopyright + "\n"); - w.write("projection = " + strProjection + "\n"); - w.write("geoid = " + strGeoid + "\n"); - w.write("xtsize = " + (int) tilesSize.getWidth() + "\n"); - w.write("ytsize = " + (int) tilesSize.getHeight() + "\n"); - w.write("xtratio = " + (nbTotalTiles / 360.0) + "\n"); - w.write("ytratio = " + (nbTotalTiles / 360.0) + "\n"); - w.write("xtoffset = " + (nbTotalTiles / 2.0) + "\n"); - w.write("ytoffset = " + (nbTotalTiles / 2.0) + "\n"); - w.write("xtmin = " + xMin + "\n"); - w.write("xtmax = " + xMax + "\n"); - w.write("ytmin = " + (nbTotalTiles - yMax) + "\n"); - w.write("ytmax = " + (nbTotalTiles - yMin) + "\n"); - w.write("background = " + "#FFFFFF" + "\n"); - w.write("imgformat = " + strImageFormat + "\n"); - w.write("\n"); - w.flush(); - w.close(); + String metaDataStr; + try (StringWriter w = new StringWriter()) { + w.write("[level]\n"); + w.write("id = " + strID + "\n"); + w.write("name = " + strName + "\n"); + w.write("scale = " + strScale + "\n"); + w.write("datasource = " + strDataSource + "\n"); + w.write("copyright = " + strCopyright + "\n"); + w.write("projection = " + strProjection + "\n"); + w.write("geoid = " + strGeoid + "\n"); + w.write("xtsize = " + (int) tilesSize.getWidth() + "\n"); + w.write("ytsize = " + (int) tilesSize.getHeight() + "\n"); + w.write("xtratio = " + (nbTotalTiles / 360.0) + "\n"); + w.write("ytratio = " + (nbTotalTiles / 360.0) + "\n"); + w.write("xtoffset = " + (nbTotalTiles / 2.0) + "\n"); + w.write("ytoffset = " + (nbTotalTiles / 2.0) + "\n"); + w.write("xtmin = " + xMin + "\n"); + w.write("xtmax = " + xMax + "\n"); + w.write("ytmin = " + (nbTotalTiles - yMax) + "\n"); + w.write("ytmax = " + (nbTotalTiles - yMin) + "\n"); + w.write("background = " + "#FFFFFF" + "\n"); + w.write("imgformat = " + strImageFormat + "\n"); + w.write("\n"); + w.flush(); + metaDataStr = w.toString(); + } // add the metadata file into map - packCreator.add(w.getBuffer().toString().getBytes(), AQM_LEVEL); + packCreator.add(metaDataStr.getBytes(StandardCharsets.ISO_8859_1), AQM_LEVEL); } @Override public boolean testMapSource(final MapSource mapSource) { MapSpace mapSpace = mapSource.getMapSpace(); - return (mapSpace instanceof MercatorPower2MapSpace) - && (ProjectionCategory.SPHERE.equals(mapSource.getMapSpace().getProjectionCategory()) || ProjectionCategory.ELLIPSOID - .equals(mapSource.getMapSpace().getProjectionCategory())); + ProjectionCategory projectionCategory = mapSpace.getProjectionCategory(); + + return (mapSpace instanceof MercatorPower2MapSpace) && (ProjectionCategory.SPHERE.equals(projectionCategory) + || ProjectionCategory.ELLIPSOID.equals(projectionCategory)); } @Override @@ -323,26 +342,35 @@ public class AlpineQuestMap extends AtlasCreator { } } - private final void addLevelDelimiter() throws IOException { + private void addLevelDelimiter() throws IOException { // add empty level delimiter file packCreator.add(new byte[0], AQM_LEVEL_DELIMITER); } - private final void addLevelTiles() throws InterruptedException, MapCreationException { + private void addLevelTiles() throws InterruptedException, MapCreationException { atlasProgress.initMapCreation((xMax - xMin + 1) * (yMax - yMin + 1)); // number of tiles for this zoom level final long nbTotalTiles = (256 * Math.round(Math.pow(2, map.getZoom()))) / tileSize; // tile resizing - BufferedImage tileImage = null; - Graphics2D graphics = null; - ArrayOutputStream buffer = null; - TileImageDataWriter writer = null; + BufferedImage tileImage; + Graphics2D graphics; + ArrayOutputStream buffer; + TileImageDataWriter writer; if ((parameters != null) || (xResizeRatio != 1.0) || (yResizeRatio != 1.0)) { + int width; + int height; + if (parameters != null) { + width = parameters.getWidth(); + height = parameters.getHeight(); + } else { + width = 256; + height = 256; + } // resize image - tileImage = new BufferedImage(parameters.getWidth(), parameters.getHeight(), BufferedImage.TYPE_3BYTE_BGR); + tileImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); // associated graphics with affine transform graphics = tileImage.createGraphics(); @@ -350,49 +378,59 @@ public class AlpineQuestMap extends AtlasCreator { graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); // image compression writer - writer = parameters.getFormat().getDataWriter(); + writer = parameters.getFormat().getDataWriterBuilder().build(); // buffer to store compressed image buffer = new ArrayOutputStream(3 * parameters.getWidth() * parameters.getHeight()); ImageIO.setUseCache(false); - writer.initialize(); + } else { + tileImage = null; + graphics = null; + buffer = null; + writer = null; } - for (int x = xMin; x <= xMax; x++) { - for (int y = yMin; y <= yMax; y++) { - checkUserAbort(); + try { + for (int x = xMin; x <= xMax; x++) { + for (int y = yMin; y <= yMax; y++) { + checkUserAbort(); - atlasProgress.incMapCreationProgress(); + atlasProgress.incMapCreationProgress(); - try { - // retrieve the tile data (already re-sampled if needed) - byte[] sourceTileData = mapDlTileProvider.getTileData(x, y); + try { + // retrieve the tile data (already re-sampled if needed) + byte[] sourceTileData = mapDlTileProvider.getTileData(x, y); - if (sourceTileData != null) { - // there is some data - if ((graphics != null) && (buffer != null) && (writer != null)) { - // need to resize the tile - final BufferedImage tile = ImageIO.read(new ByteArrayInputStream(sourceTileData)); - graphics.drawImage(tile, 0, 0, null); + if (sourceTileData != null) { + // there is some data + if (graphics != null && writer != null) { + // need to resize the tile + final BufferedImage tile = ImageIO.read(new ByteArrayInputStream(sourceTileData)); + graphics.drawImage(tile, 0, 0, null); - buffer.reset(); + buffer.reset(); - writer.processImage(tileImage, buffer); + writer.processImage(tileImage, buffer); - sourceTileData = buffer.toByteArray(); + sourceTileData = buffer.toByteArray(); - if (sourceTileData == null) - throw new MapCreationException("Image resizing failed.", map); + if (sourceTileData == null) { + throw new MapCreationException("Image resizing failed.", map); + } + } + + packCreator.add(sourceTileData, "" + x + "_" + (nbTotalTiles - y)); // y tiles count began + // by + // bottom in AQM } - - packCreator.add(sourceTileData, "" + x + "_" + (nbTotalTiles - y)); // y tiles count began by - // bottom in AQM + } catch (IOException e) { + throw new MapCreationException("Error writing tile image: " + e.getMessage(), map, e); } - } catch (IOException e) { - throw new MapCreationException("Error writing tile image: " + e.getMessage(), map, e); } } + } finally { + IOUtils.closeQuietly(writer); } } diff --git a/src/main/java/mobac/program/atlascreators/AndNav.java b/mobac/src/main/java/mobac/program/atlascreators/AndNav.java similarity index 90% rename from src/main/java/mobac/program/atlascreators/AndNav.java rename to mobac/src/main/java/mobac/program/atlascreators/AndNav.java index 2517c0c..1c0eb29 100644 --- a/src/main/java/mobac/program/atlascreators/AndNav.java +++ b/mobac/src/main/java/mobac/program/atlascreators/AndNav.java @@ -1,27 +1,26 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; import mobac.program.annotations.AtlasCreatorName; - /** * Creates maps using the AndNav atlas format. - * + *

      * Please note that this atlas format ignores the defined atlas structure. It * uses a separate directory for each used map source and inside one directory * for each zoom level. diff --git a/src/main/java/mobac/program/atlascreators/AtlasCreator.java b/mobac/src/main/java/mobac/program/atlascreators/AtlasCreator.java similarity index 77% rename from src/main/java/mobac/program/atlascreators/AtlasCreator.java rename to mobac/src/main/java/mobac/program/atlascreators/AtlasCreator.java index 2c26d48..2898c97 100644 --- a/src/main/java/mobac/program/atlascreators/AtlasCreator.java +++ b/mobac/src/main/java/mobac/program/atlascreators/AtlasCreator.java @@ -1,35 +1,30 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.EnumSet; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; +import mobac.exceptions.MapSourceInitializationException; import mobac.gui.AtlasProgress; import mobac.program.AtlasThread; import mobac.program.PauseResumeHandler; import mobac.program.atlascreators.tileprovider.TileProvider; import mobac.program.interfaces.AtlasInterface; +import mobac.program.interfaces.InitializableMapSource; import mobac.program.interfaces.LayerInterface; import mobac.program.interfaces.MapInterface; import mobac.program.interfaces.MapSource; @@ -37,25 +32,35 @@ import mobac.program.model.AtlasOutputFormat; import mobac.program.model.Settings; import mobac.program.model.TileImageFormat; import mobac.program.model.TileImageParameters; -import mobac.utilities.Charsets; import mobac.utilities.Utilities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Logger; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.EnumSet; /** * Abstract base class for all AtlasCreator implementations. - * + *

      * The general call schema is as follows: *

        - *
      1. AtlasCreator instantiation via {@link AtlasOutputFormat#createAtlasCreatorInstance()}
      2. - *
      3. AtlasCreator atlas initialization via {@link #startAtlasCreation(AtlasInterface, File)}
      4. - *
      5. 1 to n times {@link #initializeMap(MapInterface, TileProvider)} followed by {@link #createMap()}
      6. + *
      7. AtlasCreator instantiation via + * {@link AtlasOutputFormat#createAtlasCreatorInstance()}
      8. + *
      9. AtlasCreator atlas initialization via + * {@link #startAtlasCreation(AtlasInterface, File)}
      10. + *
      11. 1 to n times {@link #initializeMap(MapInterface, TileProvider)} followed + * by {@link #createMap()}
      12. *
      13. AtlasCreator atlas finalization via {@link #finishAtlasCreation()}
      14. *
      */ public abstract class AtlasCreator { - public static final Charset TEXT_FILE_CHARSET = Charsets.ISO_8859_1; + public static final Charset TEXT_FILE_CHARSET = StandardCharsets.ISO_8859_1; protected final Logger log; @@ -99,28 +104,31 @@ public abstract class AtlasCreator { * Default constructor - initializes the logging environment */ protected AtlasCreator() { - log = Logger.getLogger(this.getClass()); - }; + log = LoggerFactory.getLogger(this.getClass()); + } /** * @param customAtlasDir - * if not null the customAtlasDir is used instead of the generated atlas directory name + * if not null the customAtlasDir is used instead of the + * generated atlas directory name * @throws InterruptedException * @see AtlasCreator */ - public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) throws AtlasTestException, IOException, - InterruptedException { + public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) + throws AtlasTestException, IOException, InterruptedException { this.atlas = atlas; testAtlas(); if (customAtlasDir == null) { - // No explicit atlas output directory has been set - generate a new directory name + // No explicit atlas output directory has been set - generate a new directory + // name SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HHmmss"); String atlasDirName = atlas.getName() + "_" + sdf.format(new Date()); File atlasOutputDir = Settings.getInstance().getAtlasOutputDirectory(); atlasDir = new File(atlasOutputDir, atlasDirName); - } else + } else { atlasDir = customAtlasDir; + } Utilities.mkDirs(atlasDir); } @@ -151,8 +159,9 @@ public abstract class AtlasCreator { } /** - * Test if the {@link AtlasCreator} instance supports the selected {@link MapSource} - * + * Test if the {@link AtlasCreator} instance supports the selected + * {@link MapSource} + * * @param mapSource * @return true if supported otherwise false * @see AtlasCreator @@ -164,11 +173,20 @@ public abstract class AtlasCreator { */ public void initializeMap(MapInterface map, TileProvider mapTileProvider) { LayerInterface layer = map.getLayer(); - if (mapTileProvider == null) + if (mapTileProvider == null) { throw new NullPointerException(); + } this.mapDlTileProvider = mapTileProvider; this.map = map; this.mapSource = map.getMapSource(); + if (this.mapSource instanceof InitializableMapSource) { + try { + ((InitializableMapSource) this.mapSource).initialize(); + } catch (MapSourceInitializationException e) { + throw new RuntimeException("Initialization of MapSource \"" + // + this.mapSource.getName() + "\" failed: " + e.getMessage(), e); + } + } this.tileSize = mapSource.getMapSpace().getTileSize(); this.parameters = map.getParameters(); xMin = map.getMinTileCoordinate().x / tileSize; @@ -179,8 +197,9 @@ public abstract class AtlasCreator { this.atlasOutputFormat = layer.getAtlas().getOutputFormat(); Thread t = Thread.currentThread(); - if (!(t instanceof AtlasThread)) + if (!(t instanceof AtlasThread)) { throw new RuntimeException("Calling thread must be AtlasThread!"); + } AtlasThread at = (AtlasThread) t; atlasProgress = at.getAtlasProgress(); pauseResumeHandler = at.getPauseResumeHandler(); @@ -193,13 +212,15 @@ public abstract class AtlasCreator { public abstract void createMap() throws MapCreationException, InterruptedException; /** - * Checks if the user has aborted atlas creation and if true an {@link InterruptedException} is thrown. - * + * Checks if the user has aborted atlas creation and if true an + * {@link InterruptedException} is thrown. + * * @throws InterruptedException */ public void checkUserAbort() throws InterruptedException { - if (Thread.currentThread().isInterrupted()) + if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); + } pauseResumeHandler.pauseWait(); } @@ -236,22 +257,26 @@ public abstract class AtlasCreator { } /** - * Tests all maps of the currently active atlas if a custom tile image format has been specified and if the - * specified format is equal to the allowedFormat. - * - * @param allowedFormat + * Tests all maps of the currently active atlas if a custom tile image format + * has been specified and if the specified format is equal to the + * allowedFormat. + * + * @param allowedFormats * @throws AtlasTestException */ protected void performTest_AtlasTileFormat(EnumSet allowedFormats) throws AtlasTestException { for (LayerInterface layer : atlas) { for (MapInterface map : layer) { TileImageParameters parameters = map.getParameters(); - if (parameters == null) + if (parameters == null) { continue; - if (!allowedFormats.contains(parameters.getFormat())) + } + if (!allowedFormats.contains(parameters.getFormat())) { throw new AtlasTestException( "Selected custom tile format not supported - only the following format(s) are supported: " - + allowedFormats, map); + + allowedFormats, + map); + } } } } @@ -259,8 +284,9 @@ public abstract class AtlasCreator { protected void performTest_MaxMapZoom(int maxZoom) throws AtlasTestException { for (LayerInterface layer : atlas) { for (MapInterface map : layer) { - if (map.getZoom() > maxZoom) + if (map.getZoom() > maxZoom) { throw new AtlasTestException("Maximum zoom is " + maxZoom + " for this atlas format", map); + } } } } diff --git a/src/main/java/mobac/program/atlascreators/BackCountryNavigator.java b/mobac/src/main/java/mobac/program/atlascreators/BackCountryNavigator.java similarity index 82% rename from src/main/java/mobac/program/atlascreators/BackCountryNavigator.java rename to mobac/src/main/java/mobac/program/atlascreators/BackCountryNavigator.java index 1517f89..db49445 100644 --- a/src/main/java/mobac/program/atlascreators/BackCountryNavigator.java +++ b/mobac/src/main/java/mobac/program/atlascreators/BackCountryNavigator.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; @@ -20,9 +20,9 @@ import mobac.program.annotations.AtlasCreatorName; /** * Creates maps using the BCNav SQLite atlas format. - * - * - * @see http://www.backcountrynavigator.com + * + * @see https://www.backcountrynavigator.com/ */ @AtlasCreatorName("BackCountry Navigator (SQLite)") public class BackCountryNavigator extends RMapsSQLite { diff --git a/src/main/java/mobac/program/atlascreators/BigPlanetTracks.java b/mobac/src/main/java/mobac/program/atlascreators/BigPlanetTracks.java similarity index 83% rename from src/main/java/mobac/program/atlascreators/BigPlanetTracks.java rename to mobac/src/main/java/mobac/program/atlascreators/BigPlanetTracks.java index 8083ff5..c663775 100644 --- a/src/main/java/mobac/program/atlascreators/BigPlanetTracks.java +++ b/mobac/src/main/java/mobac/program/atlascreators/BigPlanetTracks.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; @@ -21,11 +21,11 @@ import mobac.program.annotations.AtlasCreatorName; import mobac.program.interfaces.MapSource; /** - * Atlas/Map creator for "BigPlanet-Maps application for Android" (offline SQLite maps) - * http://code.google.com/p/bigplanet/ + * Atlas/Map creator for "BigPlanet-Maps application for Android" (offline + * SQLite maps) http://code.google.com/p/bigplanet/ *

      - * Some source parts are taken from the "android-map.blogspot.com Version of Mobile Atlas Creator": - * http://code.google.com/p/android-map/ + * Some source parts are taken from the "android-map.blogspot.com Version of + * Mobile Atlas Creator": http://code.google.com/p/android-map/ *

      */ @AtlasCreatorName(value = "Big Planet Tracks SQLite", type = "BigPlanet") diff --git a/src/main/java/mobac/program/atlascreators/CacheBox.java b/mobac/src/main/java/mobac/program/atlascreators/CacheBox.java similarity index 86% rename from src/main/java/mobac/program/atlascreators/CacheBox.java rename to mobac/src/main/java/mobac/program/atlascreators/CacheBox.java index 9e9b5d8..502730c 100644 --- a/src/main/java/mobac/program/atlascreators/CacheBox.java +++ b/mobac/src/main/java/mobac/program/atlascreators/CacheBox.java @@ -1,27 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; - -import javax.imageio.ImageIO; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; @@ -36,8 +30,14 @@ import mobac.program.model.TileImageParameters; import mobac.program.model.TileImageParameters.Name; import mobac.utilities.Utilities; +import javax.imageio.ImageIO; +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.charset.StandardCharsets; + @AtlasCreatorName("CacheBox (PACK)") -@SupportedParameters(names = { Name.format }) +@SupportedParameters(names = {Name.format}) public class CacheBox extends AtlasCreator { private File packFile = null; @@ -47,34 +47,53 @@ public class CacheBox extends AtlasCreator { private int nextMapOffsetIndex = 0; private MapInfo activeMapInfo; + public static int swapInt(int v) { + return (v >>> 24) | (v << 24) | ((v << 8) & 0x00FF0000) | ((v >> 8) & 0x0000FF00); + } + + public static long swapLong(long v) { + long b1 = (v) & 0xff; + long b2 = (v >> 8) & 0xff; + long b3 = (v >> 16) & 0xff; + long b4 = (v >> 24) & 0xff; + long b5 = (v >> 32) & 0xff; + long b6 = (v >> 40) & 0xff; + long b7 = (v >> 48) & 0xff; + long b8 = (v >> 56) & 0xff; + + return b1 << 56 | b2 << 48 | b3 << 40 | b4 << 32 | b5 << 24 | b6 << 16 | b7 << 8 | b8; + } + @Override protected void testAtlas() throws AtlasTestException { for (LayerInterface layer : atlas) { - if (layer.getMapCount() == 0) + if (layer.getMapCount() == 0) { throw new AtlasTestException("Empty layers are not allowed", layer); + } Class mapSourceClass = layer.getMap(0).getMapSource().getClass(); for (MapInterface map : layer) { - if (!mapSourceClass.equals(map.getMapSource().getClass())) - throw new AtlasTestException( - "Different map sources are not allowed within one layer", map); + if (!mapSourceClass.equals(map.getMapSource().getClass())) { + throw new AtlasTestException("Different map sources are not allowed within one layer", map); + } } } } @Override - public void finishAtlasCreation() throws IOException { + public void finishAtlasCreation() { } @Override public void initLayerCreation(LayerInterface layer) throws IOException { nextMapOffsetIndex = 0; packFile = new File(atlasDir, layer.getName() + ".pack"); - if (packFile.exists()) + if (packFile.exists()) { Utilities.deleteFile(packFile); + } packRaFile = new RandomAccessFile(packFile, "rw"); /* - * We use the mapsource name as layer name. See feature request #2987674 - * for details. + * We use the mapsource name as layer name. See feature request #2987674 for + * details. */ writeString(layer.getMap(0).getMapSource().getName(), 32); // layer // name @@ -122,11 +141,13 @@ public class CacheBox extends AtlasCreator { public void initializeMap(MapInterface map, TileProvider mapTileProvider) { super.initializeMap(map, mapTileProvider); TileImageParameters param = map.getParameters(); - if (param != null) + if (param != null) { mapDlTileProvider = new ConvertedRawTileProvider(mapDlTileProvider, param.getFormat()); + } activeMapInfo = mapInfos[nextMapOffsetIndex++]; - if (!activeMapInfo.map.equals(map)) + if (!activeMapInfo.map.equals(map)) { throw new RuntimeException("Map does not match offset info!"); + } // Just to make sure we use the xy values from mapInfo xMin = activeMapInfo.minX; xMax = activeMapInfo.maxX; @@ -164,8 +185,9 @@ public class CacheBox extends AtlasCreator { // offset index table // Due to a bug in CacheBox we have to subtract 8 from the offset packRaFile.seek(activeMapInfo.indexTableOffset - 8); - for (long tileoffset : offsets) + for (long tileoffset : offsets) { writeLong(tileoffset); + } packRaFile.seek(pos); } catch (IOException e) { throw new MapCreationException(map, e); @@ -190,10 +212,11 @@ public class CacheBox extends AtlasCreator { @Override public void abortAtlasCreation() throws IOException { mapInfos = null; - Utilities.closeFile(packRaFile); + Utilities.closeQuietly(packRaFile); packRaFile = null; - if (packFile != null) + if (packFile != null) { Utilities.deleteFile(packFile); + } packFile = null; } @@ -204,10 +227,11 @@ public class CacheBox extends AtlasCreator { private void writeString(String text, int length) throws IOException { byte[] buf = new byte[length]; - byte[] asciiBytes = text.getBytes("ASCII"); + byte[] asciiBytes = text.getBytes(StandardCharsets.US_ASCII); System.arraycopy(asciiBytes, 0, buf, 0, Math.min(length, asciiBytes.length)); - for (int i = asciiBytes.length; i < length; i++) + for (int i = asciiBytes.length; i < length; i++) { buf[i] = ' '; + } packRaFile.write(buf); } @@ -219,24 +243,7 @@ public class CacheBox extends AtlasCreator { packRaFile.writeLong(swapLong(v)); } - public final static int swapInt(int v) { - return (v >>> 24) | (v << 24) | ((v << 8) & 0x00FF0000) | ((v >> 8) & 0x0000FF00); - } - - public final static long swapLong(long v) { - long b1 = (v >> 0) & 0xff; - long b2 = (v >> 8) & 0xff; - long b3 = (v >> 16) & 0xff; - long b4 = (v >> 24) & 0xff; - long b5 = (v >> 32) & 0xff; - long b6 = (v >> 40) & 0xff; - long b7 = (v >> 48) & 0xff; - long b8 = (v >> 56) & 0xff; - - return b1 << 56 | b2 << 48 | b3 << 40 | b4 << 32 | b5 << 24 | b6 << 16 | b7 << 8 | b8 << 0; - } - - private class MapInfo { + private static class MapInfo { final MapInterface map; final long indexTableOffset; @@ -247,8 +254,7 @@ public class CacheBox extends AtlasCreator { final int maxX; final int maxY; - public MapInfo(MapInterface map, long indexOffset, int tileCount, int minX, int minY, - int maxX, int maxY) { + public MapInfo(MapInterface map, long indexOffset, int tileCount, int minX, int minY, int maxX, int maxY) { super(); this.map = map; this.indexTableOffset = indexOffset; diff --git a/src/main/java/mobac/program/atlascreators/CacheWolf.java b/mobac/src/main/java/mobac/program/atlascreators/CacheWolf.java similarity index 77% rename from src/main/java/mobac/program/atlascreators/CacheWolf.java rename to mobac/src/main/java/mobac/program/atlascreators/CacheWolf.java index 372b29d..4dd35bd 100644 --- a/src/main/java/mobac/program/atlascreators/CacheWolf.java +++ b/mobac/src/main/java/mobac/program/atlascreators/CacheWolf.java @@ -1,26 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; - import mobac.exceptions.MapCreationException; import mobac.program.annotations.AtlasCreatorName; import mobac.program.annotations.SupportedParameters; @@ -33,8 +28,14 @@ import mobac.program.interfaces.MapSpace; import mobac.program.model.TileImageParameters.Name; import mobac.utilities.Utilities; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; + @AtlasCreatorName("CacheWolf (WFL)") -@SupportedParameters(names = { Name.format, Name.height, Name.width }) +@SupportedParameters(names = {Name.format, Name.height, Name.width}) public class CacheWolf extends Ozi { @Override @@ -53,26 +54,22 @@ public class CacheWolf extends Ozi { // One image per map super.createTiles(); writeWflFile(); - } else + } else { // Use automatic tiling as specified in the parameters createTiles(); + } } @Override protected void createTiles() throws InterruptedException, MapCreationException { MapTileWriter mapTileWriter; - CacheTileProvider ctp = new CacheTileProvider(mapDlTileProvider); - try { + try (CacheTileProvider ctp = new CacheTileProvider(mapDlTileProvider)) { mapDlTileProvider = ctp; mapTileWriter = new CWFileTileWriter(); MapTileBuilder mapTileBuilder = new MapTileBuilder(this, mapTileWriter, true); atlasProgress.initMapCreation(mapTileBuilder.getCustomTileCount()); mapTileBuilder.createTiles(); - } catch (IOException e) { - throw new MapCreationException(map, e); - } finally { - ctp.cleanup(); } } @@ -87,10 +84,8 @@ public class CacheWolf extends Ozi { } private void writeWflFile(String filename, int tilex, int tiley, int width, int height) throws IOException { - FileOutputStream fout = null; - try { - fout = new FileOutputStream(new File(layerDir, filename + ".wfl")); - OutputStreamWriter mapWriter = new OutputStreamWriter(fout, TEXT_FILE_CHARSET); + try (Writer mapWriter = new OutputStreamWriter(new FileOutputStream(new File(layerDir, filename + ".wfl")), + TEXT_FILE_CHARSET)) { MapSpace mapSpace = mapSource.getMapSpace(); @@ -108,7 +103,7 @@ public class CacheWolf extends Ozi { double bottomRightLon = mapSpace.cXToLon(xStart + width, zoom); double bottomRightLat = mapSpace.cYToLat(yStart + height, zoom); - double[] affine = { 0, 0, 0, 0 }; + double[] affine = {0, 0, 0, 0}; // Mobile Atlas Creator does only output maps with north at top // (no rotation). Therefore we should be able to simplify the affine @@ -116,24 +111,22 @@ public class CacheWolf extends Ozi { affine[1] = (bottomRightLon - topLeftLon) / width; affine[2] = (bottomRightLat - topLeftLat) / height; - for (double d : affine) - mapWriter.write(Double.toString(d) + "\n"); + for (double d : affine) { + mapWriter.write(d + "\n"); + } - mapWriter.write(Double.toString(topLeftLat) + "\n"); - mapWriter.write(Double.toString(topLeftLon) + "\n"); - mapWriter.write(Double.toString(bottomRightLat) + "\n"); - mapWriter.write(Double.toString(bottomRightLon) + "\n"); + mapWriter.write(topLeftLat + "\n"); + mapWriter.write(topLeftLon + "\n"); + mapWriter.write(bottomRightLat + "\n"); + mapWriter.write(bottomRightLon + "\n"); mapWriter.flush(); - mapWriter.close(); - } finally { - Utilities.closeStream(fout); } } public class CWFileTileWriter implements MapTileWriter { - public CWFileTileWriter() throws IOException { + public CWFileTileWriter() { super(); log.debug("Writing tiles to set folder: " + layerDir); } @@ -141,11 +134,8 @@ public class CacheWolf extends Ozi { public void writeTile(int tilex, int tiley, String imageFormat, byte[] tileData) throws IOException { String tileFileName = String.format("%s_%dx%d", mapName, tilex, tiley); File f = new File(layerDir, tileFileName + '.' + imageFormat); - FileOutputStream out = new FileOutputStream(f); - try { + try (FileOutputStream out = new FileOutputStream(f)) { out.write(tileData); - } finally { - Utilities.closeStream(out); } writeWflFile(tileFileName, tilex, tiley, parameters.getWidth(), parameters.getHeight()); } diff --git a/src/main/java/mobac/program/atlascreators/GCLive.java b/mobac/src/main/java/mobac/program/atlascreators/GCLive.java similarity index 86% rename from src/main/java/mobac/program/atlascreators/GCLive.java rename to mobac/src/main/java/mobac/program/atlascreators/GCLive.java index 5eaa5f1..d3d379b 100644 --- a/src/main/java/mobac/program/atlascreators/GCLive.java +++ b/mobac/src/main/java/mobac/program/atlascreators/GCLive.java @@ -1,29 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.ArrayList; -import java.util.Collections; - -import javax.imageio.ImageIO; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; @@ -38,53 +30,60 @@ import mobac.program.interfaces.MapSource; import mobac.program.model.TileImageParameters.Name; import mobac.utilities.Utilities; +import javax.imageio.ImageIO; +import java.io.File; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.ArrayList; +import java.util.Collections; + /** * File format documentation - * + * *
        * ===
        * === Reengineering of the Geocaching Live Tile Database ===
        * ===
      - * 
      + *
        * index file:
        * ===========
      - * 
      + *
        * 16 Bytes Header:
        * ----------------
      - * 
      + *
        * 00 00 00 0A		Highest index used currently for the data files. Index is incremented starting with 0.
        * 00 00 4E 20		Max. number of tiles index. Current max. number is 20000.
        * 00 00 01 4D		Number of tile entries (16 bytes) indexed.
        * 00 01 0C FF		Size of the data file with the currently used highest index.
      - * 
      + *
        * 16 Bytes per tile:
        * ------------------
      - * 
      - * 00 00			Inverse zoom level = 17 - Z. 
      + *
      + * 00 00			Inverse zoom level = 17 - Z.
        * 01 0E 16			Number of the X tile.
        * 00 B1 0E			Number of the Y tile.
        * 00 00 50 92		Start offset of the PNG data in the data file.
        * 00 9D 6 			Size of the PNG data.
        *        0 01		Index of the data file which contains the PNG data.
      - * 
      + *
        * The tiles are sorted starting by zoom level 17 (INVZ = 0).
      - * 
      + *
        * data file:
        * ----------
      - * 
      + *
        * Max. 32 PNGs concated directly together.
      - * 
      - * 
      + *
      + *
        * [0] - [x] directories:
        * ----------------------
      - * 
      + *
        * Max. 32 data files per directory. The data files are named from 'data0' to 'dataN'.
        * 
      */ @AtlasCreatorName("Geocaching Live offline map") -@SupportedParameters(names = { Name.format }) +@SupportedParameters(names = {Name.format}) public class GCLive extends AtlasCreator { private static final int MAX_TILES = 65535; @@ -101,7 +100,8 @@ public class GCLive extends AtlasCreator { long tileCount = 0; for (LayerInterface layer : atlas) { for (MapInterface map : layer) { - // We can not use map.calculateTilesToDownload() because be need the full tile count not the sparse + // We can not use map.calculateTilesToDownload() because be need the full tile + // count not the sparse int tileSize_t = 256; // Everything else is not allowed int xMin_t = map.getMinTileCoordinate().x / tileSize_t; int xMax_t = map.getMaxTileCoordinate().x / tileSize_t; @@ -110,9 +110,10 @@ public class GCLive extends AtlasCreator { tileCount += (xMax_t - xMin_t + 1) * (yMax_t - yMin_t + 1); } // Check for max tile count <= 65535 - if (tileCount > MAX_TILES) - throw new AtlasTestException("Tile count too high in layer " + layer.getName() - + "\n - please select smaller/fewer areas"); + if (tileCount > MAX_TILES) { + throw new AtlasTestException( + "Tile count too high in layer " + layer.getName() + "\n - please select smaller/fewer areas"); + } } } @@ -153,7 +154,7 @@ public class GCLive extends AtlasCreator { atlasProgress.initMapCreation((xMax - xMin + 1) * (yMax - yMin + 1)); ImageIO.setUseCache(false); - //byte[] emptyTileData = Utilities.createEmptyTileData(mapSource); + // byte[] emptyTileData = Utilities.createEmptyTileData(mapSource); for (int x = xMin; x <= xMax; x++) { for (int y = yMin; y <= yMax; y++) { @@ -161,8 +162,9 @@ public class GCLive extends AtlasCreator { atlasProgress.incMapCreationProgress(); try { byte[] sourceTileData = mapDlTileProvider.getTileData(x, y); - if (sourceTileData != null) + if (sourceTileData != null) { mapTileWriter.writeTile(x, y, null, sourceTileData); + } // else // mapTileWriter.writeTile(x, y, null, emptyTileData); } catch (IOException e) { @@ -172,82 +174,6 @@ public class GCLive extends AtlasCreator { } } - protected class GCLiveWriter implements MapTileWriter { - - private File mapDir; - - private int dataDirCounter = 0; - private int dataFileCounter = 0; - private int imageCounter = 0; - - private RandomAccessFile currentDataFile; - - private ArrayList headerEntries; - - public GCLiveWriter(File mapDir) throws IOException { - super(); - this.mapDir = mapDir; - Utilities.mkDir(mapDir); - headerEntries = new ArrayList(MAX_TILES); - prepareDataFile(); - } - - private void prepareDataFile() throws IOException { - if (currentDataFile != null) - Utilities.closeFile(currentDataFile); - currentDataFile = null; - File dataDir = new File(mapDir, Integer.toString(dataDirCounter)); - Utilities.mkDir(dataDir); - File dataFile = new File(dataDir, "data" + Integer.toString(dataFileCounter)); - currentDataFile = new RandomAccessFile(dataFile, "rw"); - imageCounter = 0; - } - - public void writeTile(int tilex, int tiley, String tileType, byte[] tileData) throws IOException { - imageCounter++; - if (imageCounter >= 32) { - dataFileCounter++; - if (dataFileCounter % 32 == 0) { - dataDirCounter++; - if (dataDirCounter >= 32) - throw new RuntimeException("Maximum number of tiles exceeded"); - } - prepareDataFile(); - } - long offset = currentDataFile.getFilePointer(); - currentDataFile.write(tileData); - int len = tileData.length; - - GCHeaderEntry header = new GCHeaderEntry(zoom, tilex, tiley, dataFileCounter, (int) offset, len); - headerEntries.add(header); - } - - public void finalizeMap() throws IOException { - int dataPos = (int) currentDataFile.getFilePointer(); - Utilities.closeFile(currentDataFile); - Collections.sort(headerEntries); - - RandomAccessFile indexFile; - indexFile = new RandomAccessFile(new File(mapDir, "index"), "rw"); - - // Write index header (first 16 bytes) - indexFile.seek(0); - int dataFileIndex = dataDirCounter * 32 + dataFileCounter; - indexFile.writeInt(dataFileIndex); // Highest index used currently for the data files. Index is incremented - // starting with 0. - indexFile.writeInt(headerEntries.size()); // Max. number of tiles index. Current max. number is 20000. - indexFile.writeInt(headerEntries.size()); // Number of tile entries (16 bytes) indexed. - indexFile.writeInt(dataPos); // Size of the data file with the currently used highest index. - - for (GCHeaderEntry entry : headerEntries) { - entry.writeHeader(indexFile); - System.out.println(entry); - } - headerEntries = null; - Utilities.closeFile(indexFile); - } - } - public static class GCHeaderEntry implements Comparable { public final int zoom; public final int tilex; @@ -286,18 +212,24 @@ public class GCLive extends AtlasCreator { } public int compareTo(GCHeaderEntry o) { - if (zoom > o.zoom) + if (zoom > o.zoom) { return -1; - if (zoom < o.zoom) + } + if (zoom < o.zoom) { return 1; - if (tilex > o.tilex) + } + if (tilex > o.tilex) { return 1; - if (tilex < o.tilex) + } + if (tilex < o.tilex) { return -1; - if (tiley > o.tiley) + } + if (tiley > o.tiley) { return 1; - if (tiley < o.tiley) + } + if (tiley < o.tiley) { return -1; + } return 0; } @@ -308,4 +240,82 @@ public class GCLive extends AtlasCreator { } } + + protected class GCLiveWriter implements MapTileWriter { + + private final File mapDir; + + private int dataDirCounter = 0; + private int dataFileCounter = 0; + private int imageCounter = 0; + + private RandomAccessFile currentDataFile; + + private ArrayList headerEntries; + + public GCLiveWriter(File mapDir) throws IOException { + super(); + this.mapDir = mapDir; + Utilities.mkDir(mapDir); + headerEntries = new ArrayList(MAX_TILES); + prepareDataFile(); + } + + private void prepareDataFile() throws IOException { + if (currentDataFile != null) { + Utilities.closeQuietly(currentDataFile); + } + currentDataFile = null; + File dataDir = new File(mapDir, Integer.toString(dataDirCounter)); + Utilities.mkDir(dataDir); + File dataFile = new File(dataDir, "data" + dataFileCounter); + currentDataFile = new RandomAccessFile(dataFile, "rw"); + imageCounter = 0; + } + + public void writeTile(int tilex, int tiley, String tileType, byte[] tileData) throws IOException { + imageCounter++; + if (imageCounter >= 32) { + dataFileCounter++; + if (dataFileCounter % 32 == 0) { + dataDirCounter++; + if (dataDirCounter >= 32) { + throw new RuntimeException("Maximum number of tiles exceeded"); + } + } + prepareDataFile(); + } + long offset = currentDataFile.getFilePointer(); + currentDataFile.write(tileData); + int len = tileData.length; + + GCHeaderEntry header = new GCHeaderEntry(zoom, tilex, tiley, dataFileCounter, (int) offset, len); + headerEntries.add(header); + } + + public void finalizeMap() throws IOException { + int dataPos = (int) currentDataFile.getFilePointer(); + Utilities.closeQuietly(currentDataFile); + Collections.sort(headerEntries); + + RandomAccessFile indexFile; + indexFile = new RandomAccessFile(new File(mapDir, "index"), "rw"); + + // Write index header (first 16 bytes) + indexFile.seek(0); + int dataFileIndex = dataDirCounter * 32 + dataFileCounter; + indexFile.writeInt(dataFileIndex); // Highest index used currently for the data files. Index is incremented + // starting with 0. + indexFile.writeInt(headerEntries.size()); // Max. number of tiles index. Current max. number is 20000. + indexFile.writeInt(headerEntries.size()); // Number of tile entries (16 bytes) indexed. + indexFile.writeInt(dataPos); // Size of the data file with the currently used highest index. + + for (GCHeaderEntry entry : headerEntries) { + entry.writeHeader(indexFile); + System.out.println(entry); + } + headerEntries = null; + Utilities.closeQuietly(indexFile); + } + } } diff --git a/src/main/java/mobac/program/atlascreators/Galileo.java b/mobac/src/main/java/mobac/program/atlascreators/Galileo.java similarity index 89% rename from src/main/java/mobac/program/atlascreators/Galileo.java rename to mobac/src/main/java/mobac/program/atlascreators/Galileo.java index ccfc305..310adca 100644 --- a/src/main/java/mobac/program/atlascreators/Galileo.java +++ b/mobac/src/main/java/mobac/program/atlascreators/Galileo.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; diff --git a/src/main/java/mobac/program/atlascreators/GarminCustom.java b/mobac/src/main/java/mobac/program/atlascreators/GarminCustom.java similarity index 73% rename from src/main/java/mobac/program/atlascreators/GarminCustom.java rename to mobac/src/main/java/mobac/program/atlascreators/GarminCustom.java index 72e545a..3b9b5ac 100644 --- a/src/main/java/mobac/program/atlascreators/GarminCustom.java +++ b/mobac/src/main/java/mobac/program/atlascreators/GarminCustom.java @@ -1,24 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.awt.image.BufferedImage; -import java.io.IOException; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.program.annotations.AtlasCreatorName; @@ -27,14 +24,19 @@ import mobac.program.interfaces.LayerInterface; import mobac.program.model.Settings; import mobac.program.model.TileImageParameters.Name; import mobac.program.tiledatawriter.TileImageJpegDataWriter; +import mobac.program.tiledatawriter.TileImageJpegDataWriterBuilder; import mobac.utilities.stream.ArrayOutputStream; +import java.awt.image.BufferedImage; +import java.io.IOException; + @AtlasCreatorName("Garmin Custom Map (KMZ)") -@SupportedParameters(names = { Name.format_jpg }) +@SupportedParameters(names = {Name.format_jpg}) public class GarminCustom extends GoogleEarthOverlay { /** - * Each jpeg should be less than 3MB. https://forums.garmin.com/showthread.php?t=2646 + * Each jpeg should be less than 3MB. + * https://forums.garmin.com/showthread.php?t=2646 */ private static final int MAX_FILE_SIZE = 3 * 1024 * 1024; @@ -42,22 +44,23 @@ public class GarminCustom extends GoogleEarthOverlay { protected void testAtlas() throws AtlasTestException { int maxMap = Settings.getInstance().atlasFormatSpecificSettings.garminCustomMaxMapCount; for (LayerInterface layer : atlas) { - if (layer.getMapCount() > maxMap) - throw new AtlasTestException("Layer exceeeds the maximum map count of " + maxMap, layer); + if (layer.getMapCount() > maxMap) { + throw new AtlasTestException("Layer exceeds in settings.xml specified maximum map count of " + maxMap, + layer); + } } } @Override protected void writeTileImage(BufferedImage tileImage) throws MapCreationException { try { - TileImageJpegDataWriter writer; + TileImageJpegDataWriterBuilder builder; if (parameters != null) { - writer = (TileImageJpegDataWriter) parameters.getFormat().getDataWriter(); - writer = new TileImageJpegDataWriter(writer); - } else - writer = new TileImageJpegDataWriter(0.9); + builder = (TileImageJpegDataWriterBuilder) parameters.getFormat().getDataWriterBuilder(); + } else { + builder = new TileImageJpegDataWriterBuilder(0.9); + } - writer.initialize(); // The maximum file size for the jpg image is 3 MB // This OutputStream will fail if the resulting image is larger than // 3 MB - then we retry using a higher JPEG compression level @@ -65,18 +68,19 @@ public class GarminCustom extends GoogleEarthOverlay { byte[] data = null; for (int c = 99; c > 50; c -= 5) { buf.reset(); - try { + try (TileImageJpegDataWriter writer = builder.build()) { writer.processImage(tileImage, buf); data = buf.toByteArray(); break; } catch (IOException e) { log.trace("Image size too large, increasing compression to " + c); } - writer.setJpegCompressionLevel(c / 100f); + builder.setJpegCompressionLevel(c / 100f); } - if (data == null) + if (data == null) { throw new MapCreationException("Unable to create an image with less than 3 MB!", map); - String imageFileName = "files/" + cleanedMapName + "." + writer.getType(); + } + String imageFileName = "files/" + cleanedMapName + "." + builder.getType(); kmzOutputStream.writeStoredEntry(imageFileName, data); addMapToKmz(imageFileName); } catch (Exception e) { diff --git a/mobac/src/main/java/mobac/program/atlascreators/GeoPackage.java b/mobac/src/main/java/mobac/program/atlascreators/GeoPackage.java new file mode 100644 index 0000000..5f349ba --- /dev/null +++ b/mobac/src/main/java/mobac/program/atlascreators/GeoPackage.java @@ -0,0 +1,250 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.atlascreators; + +import mobac.exceptions.AtlasTestException; +import mobac.exceptions.MapCreationException; +import mobac.mapsources.mapspace.MercatorPower2MapSpace; +import mobac.program.ProgramInfo; +import mobac.program.annotations.AtlasCreatorName; +import mobac.program.annotations.SupportedParameters; +import mobac.program.interfaces.AtlasInterface; +import mobac.program.interfaces.MapSource; +import mobac.program.model.TileImageParameters.Name; +import mobac.utilities.Utilities; + +import java.io.File; +import java.io.IOException; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * Warning: This implementation is defect and incomplete! + *

      + * https://sourceforge.net/p/mobac/feature-requests/263/ + *

      + * http://www.geopackage.org/spec/ + */ +@AtlasCreatorName(value = "GeoPackage SQLite", type = "GeoPackage") +@SupportedParameters(names = {Name.format}) +public class GeoPackage extends AbstractSQLite { + + private static final double PIXEL_WORLD_CONST = 156543.0339280409984; + + private static final String CREATE_TABLE_CONTENTS = "CREATE TABLE gpkg_contents " + + "(table_name TEXT NOT NULL PRIMARY KEY, data_type TEXT NOT NULL, identifier TEXT UNIQUE, " + + "description TEXT DEFAULT '', last_change DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')), " + + "min_x DOUBLE, min_y DOUBLE, max_x DOUBLE, max_y DOUBLE, srs_id INTEGER, " + + "CONSTRAINT fk_gc_r_srs_id FOREIGN KEY (srs_id) REFERENCES gpkg_spatial_ref_sys(srs_id))"; + + private static final String CREATE_TABLE_SPATIAL_REF_SYS = "CREATE TABLE gpkg_spatial_ref_sys " + + "(srs_name TEXT NOT NULL, srs_id INTEGER NOT NULL PRIMARY KEY, organization TEXT NOT NULL, " + + "organization_coordsys_id INTEGER NOT NULL, definition TEXT NOT NULL, description TEXT)"; + + private static final String CREATE_TABLE_TILE_MATRIX = "CREATE TABLE gpkg_tile_matrix " + + "(table_name TEXT NOT NULL, zoom_level INTEGER NOT NULL, matrix_width INTEGER NOT NULL, " + + "matrix_height INTEGER NOT NULL, tile_width INTEGER NOT NULL, tile_height INTEGER NOT NULL, " + + "pixel_x_size DOUBLE NOT NULL, pixel_y_size DOUBLE NOT NULL, " + + "CONSTRAINT pk_ttm PRIMARY KEY (table_name, zoom_level), " + + "CONSTRAINT fk_tmm_table_name FOREIGN KEY (table_name) REFERENCES gpkg_contents(table_name))"; + + private static final String CREATE_TABLE_TILE_MATRIX_SET = "CREATE TABLE gpkg_tile_matrix_set " + + "(table_name TEXT NOT NULL PRIMARY KEY, srs_id INTEGER NOT NULL, min_x DOUBLE NOT NULL, " + + "min_y DOUBLE NOT NULL, max_x DOUBLE NOT NULL, max_y DOUBLE NOT NULL, " + + "CONSTRAINT fk_gtms_table_name FOREIGN KEY (table_name) REFERENCES gpkg_contents(table_name), " + + "CONSTRAINT fk_gtms_srs FOREIGN KEY (srs_id) REFERENCES gpkg_spatial_ref_sys(srs_id))"; + + private static final String CREATE_TABLE_TILES = "CREATE TABLE tiles " + + "(id INTEGER PRIMARY KEY AUTOINCREMENT, zoom_level INTEGER NOT NULL, " + + "tile_column INTEGER NOT NULL, tile_row INTEGER NOT NULL, tile_data BLOB NOT NULL, " + + "UNIQUE (zoom_level, tile_column, tile_row))"; + + private static final String INSERT_TILE = "INSERT INTO tiles " + + "(zoom_level, tile_column, tile_row, tile_data) VALUES (?, ?, ?, ?)"; + private double minLon, minLat, maxLat, maxLon; + private boolean atlasInitialized = false; + + public GeoPackage() { + super(); + } + + @Override + public boolean testMapSource(MapSource mapSource) { + return MercatorPower2MapSpace.INSTANCE_256.equals(mapSource.getMapSpace()); + } + + @Override + protected String getDatabaseFileName() { + return atlas.getName() + ".gpkg"; + } + + @Override + public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) + throws IOException, AtlasTestException, InterruptedException { + super.startAtlasCreation(atlas, customAtlasDir); + Utilities.mkDir(atlasDir); + minLat = Double.POSITIVE_INFINITY; + minLon = Double.POSITIVE_INFINITY; + maxLat = Double.NEGATIVE_INFINITY; + maxLon = Double.NEGATIVE_INFINITY; + } + + @Override + public void createMap() throws MapCreationException, InterruptedException { + try { + if (!atlasInitialized) { + atlasInitialized = true; + openConnection(); + initializeDB(); + } + createTiles(); + } catch (SQLException | IOException e) { + throw new MapCreationException("Error writing SQL database \"" + databaseFile + "\": " + e.getMessage(), + map, e); + } + } + + private void initializeDB() throws SQLException { + Statement stat = conn.createStatement(); + stat.executeUpdate(CREATE_TABLE_CONTENTS); + stat.executeUpdate(CREATE_TABLE_SPATIAL_REF_SYS); + stat.executeUpdate(CREATE_TABLE_TILE_MATRIX); + stat.executeUpdate(CREATE_TABLE_TILE_MATRIX_SET); + stat.executeUpdate(CREATE_TABLE_TILES); + + stat.executeUpdate("INSERT INTO gpkg_spatial_ref_sys VALUES(' ',-1,'NONE',-1,'undefined',NULL)"); + stat.executeUpdate("INSERT INTO gpkg_spatial_ref_sys VALUES(' ',0,'NONE',0,'undefined',NULL)"); + stat.executeUpdate("INSERT INTO gpkg_spatial_ref_sys VALUES('WGS 84 / World Mercator',3395,'epsg',3395,' " + + "PROJCS[\"WGS 84 / World Mercator\",GEOGCS[\"WGS 84\", DATUM[\"WGS_1984\"," + + "SPHEROID[\"WGS 84\",6378137,298.257223563, AUTHORITY[\"EPSG\",\"7030\"]]," + + "AUTHORITY[\"EPSG\",\"6326\"]], PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]], " + + "UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]], " + + "AUTHORITY[\"EPSG\",\"4326\"]],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]], " + + "PROJECTION[\"Mercator_1SP\"],PARAMETER[\"central_meridian\",0], PARAMETER[\"scale_factor\",1]," + + "PARAMETER[\"false_easting\",0], PARAMETER[\"false_northing\",0], AUTHORITY[\"EPSG\",\"3395\"], " + + "AXIS[\"Easting\",EAST],AXIS[\"Northing\",NORTH]] ',NULL)"); + stat.executeUpdate("INSERT INTO gpkg_spatial_ref_sys VALUES('WGS 84 / Pseudo-Mercator',3857,'epsg',3857,' " + + "PROJCS[\"WGS 84 / Pseudo-Mercator\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\", " + + "SPHEROID[\"WGS 84\",6378137,298.257223563,AUTHORITY[\"EPSG\",\"7030\"]]," + + "AUTHORITY[\"EPSG\",\"6326\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\", \"8901\"]]," + + "UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]," + + "AUTHORITY[\"EPSG\",\"9122\"]]AUTHORITY[\"EPSG\",\"4326\"]]," + + "PROJECTION[\"Mercator_1SP\"],PARAMETER[\"central_meridian\",0]," + + "PARAMETER[ \"scale_factor\",1],PARAMETER[\"false_easting\",0]," + + "PARAMETER[ \"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]]," + + "AXIS[ \"X\",EAST],AXIS[\"Y\",NORTH] ',NULL)"); + stat.executeUpdate("INSERT INTO gpkg_spatial_ref_sys VALUES('WGS 84',4326,'epsg',4326," + + "'GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137, 298.257223563," + + "AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\", \"6326\"]],PRIMEM[\"Greenwich\",0," + + "AUTHORITY[\"EPSG\",\"8901\"]],UNIT [\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9122\"]]," + + "AUTHORITY[\"EPSG\",\"4326\"]]',NULL)"); + stat.executeUpdate("INSERT INTO gpkg_spatial_ref_sys VALUES('WGS 84 / Scaled World Mercator',9804,'epsg',9804," + + "'PROJCS[\"unnamed\",GEOGCS[\"WGS 84\", DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563, " + + "AUTHORITY[\"EPSG\",\"7030\"]],AUTHORITY[\"EPSG\",\"6326\"]], PRIMEM[\"Greenwich\",0]," + + "UNIT[\"degree\",0.0174532925199433], AUTHORITY[\"EPSG\",\"4326\"]],PROJECTION[\"Mercator_1SP\"]," + + "PARAMETER[\"central_meridian\",0], PARAMETER[\"scale_factor\",0.803798909747978]," + + "PARAMETER[\"false_easting\",0], PARAMETER[\"false_northing\",0], " + + "UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]]] ',NULL)"); + + stat.close(); + } + + @Override + protected void createTiles() throws InterruptedException, MapCreationException { + super.createTiles(); + String sql = "INSERT INTO gpkg_tile_matrix VALUES('tiles',?,?,?,256,256,?,?)"; + try (PreparedStatement prepStmt = conn.prepareStatement(sql)) { + prepStmt.setInt(1, map.getZoom()); + prepStmt.setInt(2, xMax - xMin + 1); // matrix_width + prepStmt.setInt(3, yMax - yMin + 1); // matrix_height + double pixel_size = PIXEL_WORLD_CONST / Math.pow(2.0, map.getZoom()); + prepStmt.setDouble(4, pixel_size); // pixel_x_size + prepStmt.setDouble(5, pixel_size); // pixel_y_size + prepStmt.executeUpdate(); + conn.commit(); + } catch (SQLException e) { + throw new MapCreationException(map, e); + } + + } + + private double lonToMetersX(double lon) { + return lon * Math.PI * 6378137.0 / 180.0; + } + + private double latToMetersY(double lat) { + double metersY = Math.log(Math.tan((90 + lat) * Math.PI / 360.0)) / (Math.PI / 180.0); + metersY = metersY * Math.PI * 6378137.0 / 180.0; + return metersY; + } + + @Override + protected void updateTileMetaInfo() throws SQLException { + minLon = Math.min(minLon, map.getMinLon()); + minLat = Math.min(minLat, map.getMinLat()); + maxLat = Math.max(maxLat, map.getMaxLon()); + maxLon = Math.max(maxLon, map.getMaxLat()); + + double min_y = latToMetersY(minLat); + double max_y = latToMetersY(maxLat); + double min_x = lonToMetersX(minLon); + double max_x = lonToMetersX(maxLon); + + try (Statement stat = conn.createStatement()) { + stat.execute("DELETE FROM gpkg_contents;"); + stat.execute("DELETE FROM gpkg_tile_matrix_set;"); + } + + String sql1 = "INSERT INTO gpkg_contents " + + "(rowid, table_name, data_type, identifier, description, min_x, min_y, max_x, max_y,srs_id) " + + "VALUES (1,'tiles','tiles','Raster Tiles',?,?,?,?,?,3857)"; + try (PreparedStatement prepStmt = conn.prepareStatement(sql1)) { + prepStmt.setString(1, "created by " + ProgramInfo.getCompleteTitle()); + prepStmt.setDouble(2, min_x); // min_x + prepStmt.setDouble(3, min_y); // min_y + prepStmt.setDouble(4, max_x); // max_x + prepStmt.setDouble(5, max_y); // max_y + prepStmt.executeUpdate(); + } + + String sql2 = "INSERT INTO gpkg_tile_matrix_set VALUES('tiles',3857,?,?,?,?)"; + try (PreparedStatement prepStmt = conn.prepareStatement(sql2)) { + prepStmt.setDouble(1, min_x); // min_x + prepStmt.setDouble(2, min_y); // min_y + prepStmt.setDouble(3, max_x); // max_x + prepStmt.setDouble(4, max_y); // max_y + prepStmt.executeUpdate(); + } + conn.commit(); + } + + @Override + protected String getTileInsertSQL() { + return INSERT_TILE; + } + + @Override + protected void writeTile(int x, int y, int z, byte[] tileData) throws SQLException, IOException { + prepStmt.setInt(1, z); + prepStmt.setInt(2, x - xMin); + prepStmt.setInt(3, y - yMin); + prepStmt.setBytes(4, tileData); + prepStmt.addBatch(); + } + +} diff --git a/src/main/java/mobac/program/atlascreators/Glopus.java b/mobac/src/main/java/mobac/program/atlascreators/Glopus.java similarity index 91% rename from src/main/java/mobac/program/atlascreators/Glopus.java rename to mobac/src/main/java/mobac/program/atlascreators/Glopus.java index 2d26756..7f3a312 100644 --- a/src/main/java/mobac/program/atlascreators/Glopus.java +++ b/mobac/src/main/java/mobac/program/atlascreators/Glopus.java @@ -1,26 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; - import mobac.exceptions.MapCreationException; import mobac.program.annotations.AtlasCreatorName; import mobac.program.atlascreators.tileprovider.TileProvider; @@ -28,6 +23,11 @@ import mobac.program.interfaces.MapInterface; import mobac.program.interfaces.MapSpace; import mobac.utilities.Utilities; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; + @AtlasCreatorName("Glopus (PNG & KAL)") public class Glopus extends Ozi { @@ -51,9 +51,8 @@ public class Glopus extends Ozi { } private void writeKalFile() throws MapCreationException { - FileOutputStream fout = null; - try { - fout = new FileOutputStream(new File(layerDir, mapName + ".kal")); + File kalFile = new File(layerDir, mapName + ".kal"); + try (FileOutputStream fout = new FileOutputStream(kalFile)) { OutputStreamWriter mapWriter = new OutputStreamWriter(fout, TEXT_FILE_CHARSET); MapSpace mapSpace = mapSource.getMapSpace(); @@ -94,8 +93,6 @@ public class Glopus extends Ozi { mapWriter.close(); } catch (IOException e) { throw new MapCreationException(map, e); - } finally { - Utilities.closeStream(fout); } } } diff --git a/src/main/java/mobac/program/atlascreators/GlopusMapFile.java b/mobac/src/main/java/mobac/program/atlascreators/GlopusMapFile.java similarity index 72% rename from src/main/java/mobac/program/atlascreators/GlopusMapFile.java rename to mobac/src/main/java/mobac/program/atlascreators/GlopusMapFile.java index d31ad62..ef22658 100644 --- a/src/main/java/mobac/program/atlascreators/GlopusMapFile.java +++ b/mobac/src/main/java/mobac/program/atlascreators/GlopusMapFile.java @@ -1,45 +1,44 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.LinkedList; - import mobac.exceptions.MapCreationException; import mobac.program.annotations.AtlasCreatorName; import mobac.program.atlascreators.impl.MapTileWriter; import mobac.program.interfaces.LayerInterface; import mobac.program.interfaces.MapSpace; import mobac.utilities.GUIExceptionHandler; -import mobac.utilities.Utilities; import mobac.utilities.stream.LittleEndianOutputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.LinkedList; + /** * General structure of an GMF file (Little Endian) - * + * *

        * DWORD Version // 0xff000002
        * DWORD cnt // Number of tiles in the file
      - * 
      - * for each tile: 
      + *
      + * for each tile:
        *   DWORD len;         // number of characters in tile name
        *   wchar_t name[len]  // map/tile name in UTF_16LE
        *   DWORD filepos      // offset where image data starts in this file
      @@ -52,10 +51,9 @@ import mobac.utilities.stream.LittleEndianOutputStream;
        *     double dLong // longitude of calibration point
        *     double dLat  // latitude of calibration point
        * END OF FILE HEADER
      - * Afterwards the tile image data follows as specified by each filepos 
      + * Afterwards the tile image data follows as specified by each filepos
        * offset.
        * 
      - * */ @AtlasCreatorName(value = "Glopus Map File (GMF)", type = "Gmf") public class GlopusMapFile extends TrekBuddy { @@ -79,10 +77,11 @@ public class GlopusMapFile extends TrekBuddy { ((GlopusTileWriter) mapTileWriter).initMap(); // Select the tile creator instance based on whether tile image // parameters has been set or not - if (parameters != null) + if (parameters != null) { createCustomTiles(); - else + } else { createTiles(); + } } catch (MapCreationException e) { throw e; } catch (InterruptedException e) { @@ -102,6 +101,24 @@ public class GlopusMapFile extends TrekBuddy { super.abortAtlasCreation(); } + private static class GlopusTile { + byte[] data; + double calNLat; + double calWLon; + double calSLat; + double calELon; + + public GlopusTile(byte[] data, double calNLat, double calWLon, double calSLat, double calELon) { + super(); + this.data = data; + this.calNLat = calNLat; + this.calWLon = calWLon; + this.calSLat = calSLat; + this.calELon = calELon; + } + + } + private class GlopusTileWriter implements MapTileWriter { final LayerInterface layer; @@ -147,81 +164,60 @@ public class GlopusMapFile extends TrekBuddy { public void finalizeMap() { File gmfFile = new File(atlasDir, layer.getName() + ".gmf"); - FileOutputStream fout = null; - try { + try (FileOutputStream fout = new FileOutputStream(gmfFile)) { int count = tiles.size(); int offset = 8 + count * ( // - 20 // nameLength, offset and calibration point count, - // tile height & width + 20 // nameLength, offset and calibration point count, + // tile height & width + (12 * 2) // name bytes + (4 * 24) // four calibration points - ); - fout = new FileOutputStream(gmfFile); - LittleEndianOutputStream out = new LittleEndianOutputStream(new BufferedOutputStream(fout, 16384)); - out.writeInt((int) 0xff000002); - out.writeInt(count); - int mapNumber = 0; - Charset charset = Charset.forName("UTF-16LE"); - for (GlopusTile gt : tiles) { - String mapName = String.format("%08d.%s", mapNumber++, tileType); - byte[] nameBytes = mapName.getBytes(charset); - out.writeInt(mapName.length());// Name length - out.write(nameBytes); - out.writeInt(offset); - out.writeInt(tileWidth); - out.writeInt(tileHeight); - out.writeInt(4); // number of calibration points - out.writeInt(0); - out.writeInt(0); - out.writeDouble(gt.calWLon); - out.writeDouble(gt.calNLat); - out.writeInt(tileHeight); - out.writeInt(tileWidth); - out.writeDouble(gt.calELon); - out.writeDouble(gt.calSLat); - out.writeInt(tileHeight); - out.writeInt(0); - out.writeDouble(gt.calELon); - out.writeDouble(gt.calNLat); - out.writeInt(0); - out.writeInt(tileWidth); - out.writeDouble(gt.calWLon); - out.writeDouble(gt.calSLat); - if (log.isTraceEnabled()) - log.trace(String.format("Offset %f %f %f %f \"%s\": 0x%x", gt.calWLon, gt.calNLat, gt.calELon, - gt.calELon, mapName, offset)); - offset += gt.data.length; + ); + try (LittleEndianOutputStream out = new LittleEndianOutputStream( + new BufferedOutputStream(fout, 16384))) { + out.writeInt(0xff000002); + out.writeInt(count); + int mapNumber = 0; + for (GlopusTile gt : tiles) { + String mapName = String.format("%08d.%s", mapNumber++, tileType); + byte[] nameBytes = mapName.getBytes(StandardCharsets.UTF_16LE); + out.writeInt(mapName.length());// Name length + out.write(nameBytes); + out.writeInt(offset); + out.writeInt(tileWidth); + out.writeInt(tileHeight); + out.writeInt(4); // number of calibration points + out.writeInt(0); + out.writeInt(0); + out.writeDouble(gt.calWLon); + out.writeDouble(gt.calNLat); + out.writeInt(tileHeight); + out.writeInt(tileWidth); + out.writeDouble(gt.calELon); + out.writeDouble(gt.calSLat); + out.writeInt(tileHeight); + out.writeInt(0); + out.writeDouble(gt.calELon); + out.writeDouble(gt.calNLat); + out.writeInt(0); + out.writeInt(tileWidth); + out.writeDouble(gt.calWLon); + out.writeDouble(gt.calSLat); + if (log.isTraceEnabled()) { + log.trace(String.format("Offset %f %f %f %f \"%s\": 0x%x", gt.calWLon, gt.calNLat, + gt.calELon, gt.calELon, mapName, offset)); + } + offset += gt.data.length; + } + out.flush(); } - out.flush(); - out = null; for (GlopusTile gt : tiles) { fout.write(gt.data); } fout.flush(); } catch (IOException e) { GUIExceptionHandler.showExceptionDialog(e); - } finally { - Utilities.closeStream(fout); } } } - - private static class GlopusTile { - byte[] data; - double calNLat; - double calWLon; - double calSLat; - double calELon; - - public GlopusTile(byte[] data, double calNLat, double calWLon, double calSLat, double calELon) { - super(); - this.data = data; - this.calNLat = calNLat; - this.calWLon = calWLon; - this.calSLat = calSLat; - this.calELon = calELon; - } - - } } diff --git a/src/main/java/mobac/program/atlascreators/GoogleEarthOverlay.java b/mobac/src/main/java/mobac/program/atlascreators/GoogleEarthOverlay.java similarity index 88% rename from src/main/java/mobac/program/atlascreators/GoogleEarthOverlay.java rename to mobac/src/main/java/mobac/program/atlascreators/GoogleEarthOverlay.java index 9c6d9aa..90e88f3 100644 --- a/src/main/java/mobac/program/atlascreators/GoogleEarthOverlay.java +++ b/mobac/src/main/java/mobac/program/atlascreators/GoogleEarthOverlay.java @@ -1,39 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.text.NumberFormat; -import java.util.zip.ZipOutputStream; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.TransformerFactoryConfigurationError; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - import mobac.exceptions.MapCreationException; import mobac.program.annotations.AtlasCreatorName; import mobac.program.atlascreators.tileprovider.TileProvider; @@ -44,10 +26,26 @@ import mobac.program.interfaces.TileImageDataWriter; import mobac.program.tiledatawriter.TileImageJpegDataWriter; import mobac.utilities.Utilities; import mobac.utilities.stream.ZipStoreOutputStream; - import org.w3c.dom.Document; import org.w3c.dom.Element; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.text.NumberFormat; +import java.util.zip.ZipOutputStream; + @AtlasCreatorName(value = "Google Earth Overlay (KMZ)", type = "GoogleEarthRasterOverlay") public class GoogleEarthOverlay extends AbstractPlainImage { @@ -60,6 +58,8 @@ public class GoogleEarthOverlay extends AbstractPlainImage { private Document kmlDoc = null; private Element groundOverlayRoot = null; + private TileImageDataWriter writer; + @Override public void initLayerCreation(LayerInterface layer) throws IOException { super.initLayerCreation(layer); @@ -68,10 +68,11 @@ public class GoogleEarthOverlay extends AbstractPlainImage { kmzOutputStream = new ZipStoreOutputStream(kmzFile); kmzOutputStream.setMethod(ZipOutputStream.STORED); try { - if (layer.getMapCount() <= 1) + if (layer.getMapCount() <= 1) { initKmlDoc(null); - else + } else { initKmlDoc(layer.getName()); + } } catch (ParserConfigurationException e) { throw new IOException(e); } @@ -84,7 +85,7 @@ public class GoogleEarthOverlay extends AbstractPlainImage { } catch (Exception e) { throw new IOException(e); } - Utilities.closeStream(kmzOutputStream); + Utilities.closeQuietly(kmzOutputStream); kmzOutputStream = null; kmzFile = null; super.finishLayerCreation(); @@ -92,7 +93,7 @@ public class GoogleEarthOverlay extends AbstractPlainImage { @Override public void abortAtlasCreation() throws IOException { - Utilities.closeStream(kmzOutputStream); + Utilities.closeQuietly(kmzOutputStream); kmzOutputStream = null; kmzFile = null; super.abortAtlasCreation(); @@ -105,23 +106,33 @@ public class GoogleEarthOverlay extends AbstractPlainImage { cleanedMapName = map.getName(); cleanedMapName = cleanedMapName.replaceAll("[[^\\p{Alnum}-_]]+", "_"); cleanedMapName = cleanedMapName.replaceAll("_{2,}", "_"); - if (cleanedMapName.endsWith("_")) + if (cleanedMapName.endsWith("_")) { cleanedMapName = cleanedMapName.substring(0, cleanedMapName.length() - 1); - if (cleanedMapName.startsWith("_")) - cleanedMapName = cleanedMapName.substring(1, cleanedMapName.length()); + } + if (cleanedMapName.startsWith("_")) { + cleanedMapName = cleanedMapName.substring(1); + } } - + protected int getBufferedImageType() { return BufferedImage.TYPE_3BYTE_BGR; } - protected void writeTileImage(BufferedImage tileImage) throws MapCreationException { - TileImageDataWriter writer; + @Override + protected void createImage() throws InterruptedException, MapCreationException { if (parameters != null) { - writer = parameters.getFormat().getDataWriter(); - } else + writer = parameters.getFormat().getDataWriterBuilder().build(); + } else { writer = new TileImageJpegDataWriter(0.9); - writer.initialize(); + } + try { + super.createImage(); + } finally { + writer.close(); + } + } + + protected void writeTileImage(BufferedImage tileImage) throws MapCreationException { try { int initialBufferSize = tileImage.getWidth() * tileImage.getHeight() / 4; ByteArrayOutputStream buf = new ByteArrayOutputStream(initialBufferSize); @@ -145,8 +156,7 @@ public class GoogleEarthOverlay extends AbstractPlainImage { private void initKmlDoc(String folderName) throws ParserConfigurationException { - DocumentBuilder builder; - builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); kmlDoc = builder.newDocument(); Element kml = kmlDoc.createElementNS("http://www.opengis.net/kml/2.2", "kml"); diff --git a/src/main/java/mobac/program/atlascreators/GpsSportsTracker.java b/mobac/src/main/java/mobac/program/atlascreators/GpsSportsTracker.java similarity index 89% rename from src/main/java/mobac/program/atlascreators/GpsSportsTracker.java rename to mobac/src/main/java/mobac/program/atlascreators/GpsSportsTracker.java index 0613af3..42e73f8 100644 --- a/src/main/java/mobac/program/atlascreators/GpsSportsTracker.java +++ b/mobac/src/main/java/mobac/program/atlascreators/GpsSportsTracker.java @@ -1,27 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; - -import javax.imageio.ImageIO; - import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; import mobac.program.annotations.AtlasCreatorName; @@ -33,15 +27,19 @@ import mobac.program.model.TileImageFormat; import mobac.program.model.TileImageType; import mobac.utilities.Utilities; +import javax.imageio.ImageIO; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + /** * Derived from {@link MobileTrailExplorer} */ @AtlasCreatorName("GPS Sports Tracker") public class GpsSportsTracker extends AtlasCreator { - private File mapDir = null; - protected String appendFileExt = ""; + private File mapDir = null; @Override public boolean testMapSource(MapSource mapSource) { @@ -61,9 +59,10 @@ public class GpsSportsTracker extends AtlasCreator { } catch (IOException e1) { throw new MapCreationException(map, e1); } - if (mapSource.getTileImageType() != TileImageType.PNG) + if (mapSource.getTileImageType() != TileImageType.PNG) { // If the tile image format is not png we have to convert it mapDlTileProvider = new ConvertedRawTileProvider(mapDlTileProvider, TileImageFormat.PNG); + } createTiles(); } @@ -80,11 +79,8 @@ public class GpsSportsTracker extends AtlasCreator { byte[] sourceTileData = mapDlTileProvider.getTileData(x, y); if (sourceTileData != null) { File f = new File(mapDir, tileFileName); - FileOutputStream out = new FileOutputStream(f); - try { + try (FileOutputStream out = new FileOutputStream(f)) { out.write(sourceTileData); - } finally { - Utilities.closeStream(out); } } } catch (IOException e) { diff --git a/src/main/java/mobac/program/atlascreators/IPhone3MapTiles5.java b/mobac/src/main/java/mobac/program/atlascreators/IPhone3MapTiles5.java similarity index 85% rename from src/main/java/mobac/program/atlascreators/IPhone3MapTiles5.java rename to mobac/src/main/java/mobac/program/atlascreators/IPhone3MapTiles5.java index 1fffad3..1870c67 100644 --- a/src/main/java/mobac/program/atlascreators/IPhone3MapTiles5.java +++ b/mobac/src/main/java/mobac/program/atlascreators/IPhone3MapTiles5.java @@ -1,30 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.awt.Point; -import java.io.File; -import java.io.IOException; -import java.sql.SQLException; -import java.sql.Statement; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.EnumSet; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; @@ -39,32 +30,46 @@ import mobac.program.model.TileImageFormat; import mobac.program.model.TileImageParameters; import mobac.program.model.TileImageType; +import java.awt.Point; +import java.io.File; +import java.io.IOException; +import java.sql.SQLException; +import java.sql.Statement; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.EnumSet; + /** * The following SQL statements create SQLite database for background map: - * - * BEGIN TRANSACTION; CREATE TABLE images(zoom int, x int, y int, flags int, length int, data blob); CREATE TABLE - * version(version int); INSERT INTO version VALUES(5); INSERT INTO version VALUES(0); - * + *

      + * BEGIN TRANSACTION; CREATE TABLE images(zoom int, x int, y int, flags int, + * length int, data blob); CREATE TABLE version(version int); INSERT INTO + * version VALUES(5); INSERT INTO version VALUES(0); + *

      * CREATE INDEX index1 on images (zoom,x,y,flags); COMMIT; - * + *

      * The columns in "images" table have the following meaning: - * - * zoom - zoom level from 1 (top level) to 23 (most detailed level). On the top level we have four squares 128x128 - * pixels, it gives 512x512 pixels. So map width = map height = 256 * 2zoom pixels. - * + *

      + * zoom - zoom level from 1 (top level) to 23 (most detailed level). On the top + * level we have four squares 128x128 pixels, it gives 512x512 pixels. So map + * width = map height = 256 * 2zoom pixels. + *

      * x, y - coordinates for given zoom level: - * - * - * - * flags - layer number. Theoretically map could contain number of layers: street, satellite, hybrid and so on. - * Practically the program shows only one layer with smallest flags value. - * + *

      + *

      + *

      + * flags - layer number. Theoretically map could contain number of layers: + * street, satellite, hybrid and so on. Practically the program shows only one + * layer with smallest flags value. + *

      * length - size of binary image in bytes. - * - * data - binary tile image in PNG or JPEG format. Practically the program supports only PNG for now. - * - * For more details regarding Web Mercator projection and coordinates please see: - * + *

      + * data - binary tile image in PNG or JPEG format. Practically the program + * supports only PNG for now. + *

      + * For more details regarding Web Mercator projection and coordinates please + * see: + *

      * http://msdn.microsoft.com/en-us/library/bb259689.aspx */ @AtlasCreatorName(value = "iPhone 3 Map Tiles v5") @@ -92,23 +97,25 @@ public class IPhone3MapTiles5 extends RMapsSQLite { TileImageType currentTit; if (parameters == null) { currentTit = map.getMapSource().getTileImageType(); - if (!allowed.contains(currentTit)) + if (!allowed.contains(currentTit)) { throw new AtlasTestException( "Map source format incompatible - tile format conversion to PNG or JPG is required for this map.", map); + } } else { currentTit = parameters.getFormat().getType(); - if (!allowed.contains(currentTit)) + if (!allowed.contains(currentTit)) { throw new AtlasTestException( "Selected custom tile format not supported - only JPG and PNG formats are supported.", map); + } } } } } @Override - protected void openConnection() throws SQLException { + protected void openConnection() throws SQLException, IOException { if (databaseFile.isFile()) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HHmmss"); databaseFile = new File(atlasDir, atlas.getName() + "_" + sdf.format(new Date()) + ".sqlitedb"); @@ -121,8 +128,9 @@ public class IPhone3MapTiles5 extends RMapsSQLite { Statement stat = conn.createStatement(); stat.executeUpdate(TABLE_IMAGES); stat.executeUpdate(INDEX_IMAGES); - if (stat.executeUpdate(TABLE_VERSION) == 0) + if (stat.executeUpdate(TABLE_VERSION) == 0) { stat.execute(TABLE_VERSION_DATA); + } stat.close(); } @@ -144,8 +152,9 @@ public class IPhone3MapTiles5 extends RMapsSQLite { throw new MapCreationException(map, e); } catch (IOException e) { Throwable t = e; - if (t.getCause() instanceof SQLException) + if (t.getCause() instanceof SQLException) { t = t.getCause(); + } throw new MapCreationException(map, t); } } diff --git a/src/main/java/mobac/program/atlascreators/MBTiles.java b/mobac/src/main/java/mobac/program/atlascreators/MBTiles.java similarity index 59% rename from src/main/java/mobac/program/atlascreators/MBTiles.java rename to mobac/src/main/java/mobac/program/atlascreators/MBTiles.java index a5a37f1..fe58111 100644 --- a/src/main/java/mobac/program/atlascreators/MBTiles.java +++ b/mobac/src/main/java/mobac/program/atlascreators/MBTiles.java @@ -1,31 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.IOException; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Statement; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.EnumSet; -import java.util.Locale; - import mobac.exceptions.AtlasTestException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; import mobac.program.annotations.AtlasCreatorName; @@ -36,23 +26,41 @@ import mobac.program.interfaces.MapSpace; import mobac.program.model.TileImageParameters; import mobac.program.model.TileImageType; +import java.io.File; +import java.io.IOException; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.EnumSet; +import java.util.Locale; +import java.util.Set; +import java.util.TreeSet; + /** - * https://github.com/mapbox/mbtiles-spec/tree/master/1.1 + * https://github.com/mapbox/mbtiles-spec/blob/master/1.3/spec.md */ @AtlasCreatorName(value = "MBTiles SQLite") public class MBTiles extends RMapsSQLite { - private static final String INSERT_SQL = "INSERT or REPLACE INTO tiles (tile_column,tile_row,zoom_level,tile_data) VALUES (?,?,?,?)"; + private static final String INSERT_TILES = "INSERT or REPLACE INTO tiles (tile_column,tile_row,zoom_level,tile_data) VALUES (?,?,?,?)"; private static final String TABLE_TILES = "CREATE TABLE IF NOT EXISTS tiles (zoom_level integer, tile_column integer, tile_row integer, tile_data blob);"; - private static final String INDEX_TILES = "CREATE INDEX IF NOT EXISTS tiles_idx on tiles (zoom_level, tile_column, tile_row)"; + private static final String INDEX_TILES = "CREATE UNIQUE INDEX IF NOT EXISTS tiles_idx on tiles (zoom_level, tile_column, tile_row)"; private static final String TABLE_METADATA = "CREATE TABLE IF NOT EXISTS metadata (name text, value text);"; private static final String INSERT_METADATA = "INSERT INTO metadata (name,value) VALUES (?,?);"; private static final String INDEX_METADATA = "CREATE UNIQUE INDEX IF NOT EXISTS metadata_idx ON metadata (name);"; - private double boundsLatMin; - private double boundsLatMax; - private double boundsLonMin; - private double boundsLonMax; + private boolean initialized = false; + + private double boundsBottom; + private double boundsTop; + private double boundsLeft; + private double boundsRight; + + private int minZoom; + + private int maxZoom; private TileImageType atlasTileImageType; @@ -66,22 +74,31 @@ public class MBTiles extends RMapsSQLite { EnumSet allowed = EnumSet.of(TileImageType.JPG, TileImageType.PNG); // Test of output format - only jpg xor png is allowed TileImageType tit = null; + Set zoomSet = new TreeSet<>(); for (LayerInterface layer : atlas) { for (MapInterface map : layer) { + if (!zoomSet.add(map.getZoom())) { + throw new AtlasTestException( + String.format("Map source format incompatible - multiple maps exists for zoom level %d. " + + "Only one map per zoom level allowed", map.getZoom()), + map); + } TileImageParameters parameters = map.getParameters(); TileImageType currentTit; if (parameters == null) { currentTit = map.getMapSource().getTileImageType(); - if (!allowed.contains(currentTit)) + if (!allowed.contains(currentTit)) { throw new AtlasTestException( "Map source format incompatible - tile format conversion to PNG or JPG is required for this map.", map); + } } else { currentTit = parameters.getFormat().getType(); - if (!allowed.contains(currentTit)) + if (!allowed.contains(currentTit)) { throw new AtlasTestException( "Selected custom tile format not supported - only JPG and PNG formats are supported.", map); + } } if (tit != null && !currentTit.equals(tit)) { throw new AtlasTestException("All maps within one atlas must use the same format (PNG or JPG). " @@ -94,7 +111,7 @@ public class MBTiles extends RMapsSQLite { } @Override - protected void openConnection() throws SQLException { + protected void openConnection() throws SQLException, IOException { if (databaseFile.isFile()) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HHmmss"); databaseFile = new File(atlasDir, atlas.getName() + "_" + sdf.format(new Date()) + ".mbtiles"); @@ -104,16 +121,22 @@ public class MBTiles extends RMapsSQLite { @Override protected void initializeDB() throws SQLException { - Statement stat = conn.createStatement(); - stat.executeUpdate(TABLE_TILES); - stat.executeUpdate(INDEX_TILES); - stat.executeUpdate(TABLE_METADATA); - stat.executeUpdate(INDEX_METADATA); - stat.close(); - boundsLatMin = Double.MAX_VALUE; - boundsLatMax = Double.MIN_VALUE; - boundsLonMin = Double.MAX_VALUE; - boundsLonMax = Double.MIN_VALUE; + if (initialized) { + return; + } + initialized = true; + try (Statement stat = conn.createStatement()) { + stat.executeUpdate(TABLE_TILES); + stat.executeUpdate(INDEX_TILES); + stat.executeUpdate(TABLE_METADATA); + stat.executeUpdate(INDEX_METADATA); + } + boundsBottom = Double.NEGATIVE_INFINITY; + boundsTop = Double.POSITIVE_INFINITY; + boundsLeft = Double.NEGATIVE_INFINITY; + boundsRight = Double.POSITIVE_INFINITY; + minZoom = Integer.MAX_VALUE; + maxZoom = 0; } @Override @@ -124,38 +147,68 @@ public class MBTiles extends RMapsSQLite { double lat1 = ms.cYToLat(map.getMinTileCoordinate().y, zoom); double lat2 = ms.cYToLat(map.getMaxTileCoordinate().y, zoom); - boundsLatMin = Math.min(boundsLatMin, Math.min(lat1, lat2)); - boundsLatMax = Math.max(boundsLatMax, Math.max(lat1, lat2)); - boundsLonMin = Math.min(boundsLonMin, Math.min(lon1, lon2)); - boundsLonMax = Math.max(boundsLonMin, Math.max(lon1, lon2)); + boundsBottom = Math.max(boundsBottom, Math.min(lat1, lat2)); + boundsTop = Math.min(boundsTop, Math.max(lat1, lat2)); + boundsLeft = Math.max(boundsLeft, Math.min(lon1, lon2)); + boundsRight = Math.min(boundsRight, Math.max(lon1, lon2)); + + minZoom = Math.min(minZoom, map.getZoom()); + maxZoom = Math.max(maxZoom, map.getZoom()); } @Override public void finishAtlasCreation() throws IOException, InterruptedException { - PreparedStatement st; - try { - st = conn.prepareStatement(INSERT_METADATA); - st.setString(1, "bounds"); - st.setString(2, String.format(Locale.ENGLISH, "%.3f,%.3f,%.3f,%.3f", boundsLonMin, boundsLatMin, - boundsLonMax, boundsLatMax)); - st.execute(); + try (PreparedStatement st = conn.prepareStatement(INSERT_METADATA)) { + + // name (string): The human-readable name of the tileset. st.setString(1, "name"); st.setString(2, atlas.getName()); st.execute(); + + // format (string): The file format of the tile data: pbf, jpg, png, webp, or an + // IETF media type for other formats. + st.setString(1, "format"); + st.setString(2, atlasTileImageType.getFileExt()); + st.execute(); + + // bounds (string of comma-separated numbers): The maximum extent of the + // rendered map area. Bounds must define an area covered by all zoom levels. The + // bounds are represented as WGS 84 latitude and longitude values, in the + // OpenLayers Bounds format (left, bottom, right, top). + if (boundsLeft < boundsRight && boundsTop > boundsBottom) { + st.setString(1, "bounds"); + st.setString(2, String.format(Locale.ENGLISH, "%.3f,%.3f,%.3f,%.3f", boundsLeft, boundsBottom, + boundsRight, boundsTop)); + st.execute(); + } + + // (number): The highest zoom level for which the tileset provides data + st.setString(1, "maxzoom"); + st.setString(2, Integer.toString(maxZoom)); + st.execute(); + + // (number): The lowest zoom level for which the tileset provides data + st.setString(1, "minzoom"); + st.setString(2, Integer.toString(minZoom)); + st.execute(); + + // type (string): overlay or baselayer st.setString(1, "type"); st.setString(2, "baselayer"); st.execute(); + + // version (number): The version of the tileset. This refers to a revision of + // the tileset itself, not of the MBTiles specification. st.setString(1, "version"); - st.setString(2, "1.1"); + st.setString(2, "1.3"); st.execute(); + + // description (string): A description of the tileset's content. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); st.setString(1, "description"); st.setString(2, atlas.getName() + " created on " + sdf.format(new Date()) + " by MOBAC"); st.execute(); - st.setString(1, "format"); - st.setString(2, atlasTileImageType.getFileExt()); - st.execute(); - st.close(); + conn.commit(); } catch (SQLException e) { throw new IOException(e); @@ -165,7 +218,7 @@ public class MBTiles extends RMapsSQLite { @Override protected String getTileInsertSQL() { - return INSERT_SQL; + return INSERT_TILES; } @Override diff --git a/src/main/java/mobac/program/atlascreators/MGMaps.java b/mobac/src/main/java/mobac/program/atlascreators/MGMaps.java similarity index 86% rename from src/main/java/mobac/program/atlascreators/MGMaps.java rename to mobac/src/main/java/mobac/program/atlascreators/MGMaps.java index e9aa98c..13373bc 100644 --- a/src/main/java/mobac/program/atlascreators/MGMaps.java +++ b/mobac/src/main/java/mobac/program/atlascreators/MGMaps.java @@ -1,33 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.RandomAccessFile; - -import javax.imageio.ImageIO; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; @@ -45,25 +33,39 @@ import mobac.program.model.TileImageParameters.Name; import mobac.utilities.Utilities; import mobac.utilities.stream.ArrayOutputStream; +import javax.imageio.ImageIO; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.RandomAccessFile; + /** * Creates maps using the MGM pack file format (.mgm). - * + *

      * Each zoom level in a different directory, 64 tiles per mgm file. - * + * *

      Format

      *
        - *
      • 2 bytes: number of tiles in this file for each tile (even for tiles that are not used, in which case the data is - * left null)
      • - *
      • 1 byte: tile x within this file; add tileX * tilesPerFileX to get global tile number
      • - *
      • 1 byte: tile y within this file; add tileY * tilesPerFileY to get global tile number
      • - *
      • 4 bytes: offset of the end of the tile data within this file (to get the offset for the start of the tile data, - * subtract the value for the previous tile, or 2 + 6 * tilesPerFile tile data 1 tile data 2 ...
      • + *
      • 2 bytes: number of tiles in this file for each tile (even for tiles that + * are not used, in which case the data is left null)
      • + *
      • 1 byte: tile x within this file; add tileX * tilesPerFileX to get global + * tile number
      • + *
      • 1 byte: tile y within this file; add tileY * tilesPerFileY to get global + * tile number
      • + *
      • 4 bytes: offset of the end of the tile data within this file (to get the + * offset for the start of the tile data, subtract the value for the previous + * tile, or 2 + 6 * tilesPerFile tile data 1 tile data 2 ...
      • *
      - * + * * @author paour */ @AtlasCreatorName(value = "MGMaps/MyTrails (MGM)", type = "MGM") -@SupportedParameters(names = { Name.format }) +@SupportedParameters(names = {Name.format}) public class MGMaps extends AtlasCreator { private static final int TILES_PER_FILE_X = 8; @@ -74,8 +76,8 @@ public class MGMaps extends AtlasCreator { private double yResizeRatio = 1.0; @Override - public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) throws AtlasTestException, IOException, - InterruptedException { + public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) + throws AtlasTestException, IOException, InterruptedException { super.startAtlasCreation(atlas, customAtlasDir); File cache_conf = new File(atlasDir, "cache.conf"); @@ -113,10 +115,11 @@ public class MGMaps extends AtlasCreator { public void createMap() throws MapCreationException, InterruptedException { MGMTileWriter mgmTileWriter = null; try { - if ((xResizeRatio != 1.0) || (yResizeRatio != 1.0)) + if ((xResizeRatio != 1.0) || (yResizeRatio != 1.0)) { mgmTileWriter = new MGMResizeTileWriter(); - else + } else { mgmTileWriter = new MGMTileWriter(); + } String name = map.getLayer().getName(); @@ -157,8 +160,10 @@ public class MGMaps extends AtlasCreator { } if (raf == null) - // Only create a file when needed + // Only create a file when needed + { raf = new RandomAccessFile(pack, "rw"); + } checkUserAbort(); atlasProgress.incMapCreationProgress(); @@ -176,12 +181,13 @@ public class MGMaps extends AtlasCreator { raf.writeChar(count); } } finally { - Utilities.closeFile(raf); + Utilities.closeQuietly(raf); } if (count == 0) { // the file doesn't contain any tiles - if (pack.exists()) + if (pack.exists()) { Utilities.deleteFile(pack); + } } } } @@ -189,8 +195,9 @@ public class MGMaps extends AtlasCreator { } catch (Exception e) { throw new MapCreationException(map, e); } finally { - if (mgmTileWriter != null) + if (mgmTileWriter != null) { mgmTileWriter.dispose(); + } } } @@ -198,8 +205,8 @@ public class MGMaps extends AtlasCreator { public boolean testMapSource(final MapSource mapSource) { MapSpace mapSpace = mapSource.getMapSpace(); return (mapSpace instanceof MercatorPower2MapSpace) - && (ProjectionCategory.SPHERE.equals(mapSource.getMapSpace().getProjectionCategory()) || ProjectionCategory.ELLIPSOID - .equals(mapSource.getMapSpace().getProjectionCategory())); + && (ProjectionCategory.SPHERE.equals(mapSource.getMapSpace().getProjectionCategory()) + || ProjectionCategory.ELLIPSOID.equals(mapSource.getMapSpace().getProjectionCategory())); } /** @@ -215,8 +222,9 @@ public class MGMaps extends AtlasCreator { throws MapCreationException { try { byte[] sourceTileData = getSourceTileData(x, y); - if (sourceTileData == null) + if (sourceTileData == null) { return -1; + } raf.seek(startPos); raf.write(sourceTileData); @@ -257,7 +265,7 @@ public class MGMaps extends AtlasCreator { graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); // image compression writer - writer = parameters.getFormat().getDataWriter(); + writer = parameters.getFormat().getDataWriterBuilder().build(); // buffer to store compressed image buffer = new ArrayOutputStream(3 * parameters.getWidth() * parameters.getHeight()); @@ -269,7 +277,6 @@ public class MGMaps extends AtlasCreator { final BufferedImage tile = mapDlTileProvider.getTileImage(x, y); graphics.drawImage(tile, 0, 0, null); buffer.reset(); - writer.initialize(); writer.processImage(tileImage, buffer); byte[] processedTileData = buffer.toByteArray(); diff --git a/src/main/java/mobac/program/atlascreators/MagellanRmp.java b/mobac/src/main/java/mobac/program/atlascreators/MagellanRmp.java similarity index 81% rename from src/main/java/mobac/program/atlascreators/MagellanRmp.java rename to mobac/src/main/java/mobac/program/atlascreators/MagellanRmp.java index 03fee29..224beb0 100644 --- a/src/main/java/mobac/program/atlascreators/MagellanRmp.java +++ b/mobac/src/main/java/mobac/program/atlascreators/MagellanRmp.java @@ -1,27 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.awt.Point; -import java.io.File; -import java.io.IOException; - -import javax.imageio.ImageIO; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; @@ -43,14 +37,20 @@ import mobac.program.interfaces.MapInterface; import mobac.program.interfaces.MapSource; import mobac.program.interfaces.MapSpace; import mobac.program.interfaces.TileImageDataWriter; +import mobac.program.interfaces.TileImageDataWriterBuilder; import mobac.program.model.TileImageParameters.Name; -import mobac.program.tiledatawriter.TileImageJpegDataWriter; +import mobac.program.tiledatawriter.TileImageJpegDataWriterBuilder; + +import javax.imageio.ImageIO; +import java.awt.Point; +import java.io.File; +import java.io.IOException; @AtlasCreatorName(value = "Magellan (RMP)", type = "Rmp") -@SupportedParameters(names = { Name.format_jpg }) +@SupportedParameters(names = {Name.format_jpg}) public class MagellanRmp extends AtlasCreator { - TileImageDataWriter tileWriter = null; + TileImageDataWriterBuilder tileWriterBuilder = null; RmpWriter rmpWriter = null; String imageName = null; int layerNum = 0; @@ -61,12 +61,13 @@ public class MagellanRmp extends AtlasCreator { } @Override - public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) throws IOException, InterruptedException, - AtlasTestException { + public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) + throws IOException, InterruptedException, AtlasTestException { super.startAtlasCreation(atlas, customAtlasDir); int mapCount = 0; - for (LayerInterface layer : atlas) + for (LayerInterface layer : atlas) { mapCount += layer.getMapCount(); + } imageName = RmpTools.buildImageName(atlas.getName()); rmpWriter = new RmpWriter(imageName, mapCount, new File(atlasDir, imageName + ".rmp")); } @@ -80,8 +81,10 @@ public class MagellanRmp extends AtlasCreator { // if (max.x - min.x > 18000 || max.y - min.y > 18000) // throw new AtlasTestException("Map too large. Max size 18000x18000"); if (map.getParameters() != null) { - if (!(map.getParameters().getFormat().getDataWriter() instanceof TileImageJpegDataWriter)) + if (!(map.getParameters().getFormat() + .getDataWriterBuilder() instanceof TileImageJpegDataWriterBuilder)) { throw new AtlasTestException("Only JPEG formats are supported", map); + } } } } @@ -91,10 +94,11 @@ public class MagellanRmp extends AtlasCreator { public void initializeMap(MapInterface map, TileProvider mapTileProvider) { super.initializeMap(map, mapTileProvider); if (parameters != null) { - tileWriter = parameters.getFormat().getDataWriter(); - } else - tileWriter = new TileImageJpegDataWriter(0.9); - tileWriter.initialize(); + tileWriterBuilder = parameters.getFormat().getDataWriterBuilder(); + } else { + tileWriterBuilder = new TileImageJpegDataWriterBuilder(0.9); + } + tileWriterBuilder.build(); } @Override @@ -107,8 +111,8 @@ public class MagellanRmp extends AtlasCreator { ImageIO.setUseCache(false); MultiImage layerImage = new MultiImage(mapSource, mapDlTileProvider, map); - try { - RmpLayer layer = createLayer(layerImage, layerNum); + try (TileImageDataWriter tileWriter = tileWriterBuilder.build()) { + RmpLayer layer = createLayer(layerImage, layerNum, tileWriter); String layerName = RmpTools.buildTileName(imageName, layerNum); TLMEntry tlmEntry = layer.getTLMFile(layerName); rmpWriter.prepareFileEntry(tlmEntry); @@ -124,8 +128,9 @@ public class MagellanRmp extends AtlasCreator { @Override public void finishAtlasCreation() throws IOException, InterruptedException { - if (rmpWriter == null) + if (rmpWriter == null) { return; // Creation already aborted + } try { rmpWriter.writeFileEntry(new Bmp2bit()); rmpWriter.writeFileEntry(new Bmp4bit()); @@ -144,21 +149,21 @@ public class MagellanRmp extends AtlasCreator { } /** - * Create a new instance of a TLM file and fill it with the data of a calibrated image - * + * Create a new instance of a TLM file and fill it with the data of a calibrated + * image + * * @param si * image to get data from * @param layer * Layer number - for status output only + * @param tileWriter * @return TLM instance * @throws InterruptedException * @throws MapCreationException * @throws IOException */ - public RmpLayer createLayer(MultiImage si, int layer) throws InterruptedException, MapCreationException, - IOException { - - int count = 0; + public RmpLayer createLayer(MultiImage si, int layer, TileImageDataWriter tileWriter) + throws InterruptedException, MapCreationException, IOException { /* --- Create instance --- */ RmpLayer rmpLayer = new RmpLayer(this); @@ -191,15 +196,15 @@ public class MagellanRmp extends AtlasCreator { double y_end = (rect.getSouth() + 90.0) / tile_height; /* - * Create the tiles - process works column wise, starting on the top left corner of the destination area. + * Create the tiles - process works column wise, starting on the top left corner + * of the destination area. */ for (int x = x_start; x < x_end; x++) { for (int y = y_start; y < y_end; y++) { - count++; /* --- Create tile --- */ - BoundingRect subrect = new BoundingRect(y * tile_height - 90, (y + 1) * tile_height - 90, x - * tile_width - 180, (x + 1) * tile_width - 180); + BoundingRect subrect = new BoundingRect(y * tile_height - 90, (y + 1) * tile_height - 90, + x * tile_width - 180, (x + 1) * tile_width - 180); Tiledata td = new Tiledata(tileWriter); td.posx = x; td.posy = y; @@ -208,9 +213,9 @@ public class MagellanRmp extends AtlasCreator { rmpLayer.addPreparedImage(td); } } - /* --- Build the TLM file --- */ - rmpLayer.buildTLMFile(tile_width, tile_height, rect.getWest(), rect.getEast(), rect.getNorth(), rect.getSouth()); + rmpLayer.buildTLMFile(tile_width, tile_height, rect.getWest(), rect.getEast(), rect.getNorth(), + rect.getSouth()); return rmpLayer; } diff --git a/src/main/java/mobac/program/atlascreators/Maplorer.java b/mobac/src/main/java/mobac/program/atlascreators/Maplorer.java similarity index 82% rename from src/main/java/mobac/program/atlascreators/Maplorer.java rename to mobac/src/main/java/mobac/program/atlascreators/Maplorer.java index 7bc941e..691bc7b 100644 --- a/src/main/java/mobac/program/atlascreators/Maplorer.java +++ b/mobac/src/main/java/mobac/program/atlascreators/Maplorer.java @@ -1,30 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Locale; - -import javax.imageio.ImageIO; - import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; import mobac.program.annotations.AtlasCreatorName; @@ -41,13 +32,21 @@ import mobac.program.interfaces.MapSpace.ProjectionCategory; import mobac.program.model.TileImageParameters.Name; import mobac.utilities.Utilities; +import javax.imageio.ImageIO; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Locale; + /** * AtlasCreator for MAPLORER ( http://maplorer.com ) - * + * * @author Werner Keilholz */ @AtlasCreatorName("Maplorer atlas format") -@SupportedParameters(names = { Name.format, Name.height, Name.width }) +@SupportedParameters(names = {Name.format, Name.height, Name.width}) public class Maplorer extends AtlasCreator { private static final String FILENAME_PATTERN = "map_%s%d.%s"; @@ -61,22 +60,19 @@ public class Maplorer extends AtlasCreator { public boolean testMapSource(MapSource mapSource) { MapSpace mapSpace = mapSource.getMapSpace(); - return (mapSpace instanceof MercatorPower2MapSpace && ProjectionCategory.SPHERE.equals(mapSpace - .getProjectionCategory())); + return (mapSpace instanceof MercatorPower2MapSpace + && ProjectionCategory.SPHERE.equals(mapSpace.getProjectionCategory())); } protected void createCustomTiles() throws InterruptedException, MapCreationException { log.debug("Starting map creation using custom parameters: " + parameters); - CacheTileProvider ctp = new CacheTileProvider(mapDlTileProvider); - try { + try (CacheTileProvider ctp = new CacheTileProvider(mapDlTileProvider)) { mapDlTileProvider = ctp; MapTileBuilder mapTileBuilder = new MapTileBuilder(this, mapTileWriter, true); atlasProgress.initMapCreation(mapTileBuilder.getCustomTileCount()); mapTileBuilder.createTiles(); - } finally { - ctp.cleanup(); } } @@ -88,10 +84,11 @@ public class Maplorer extends AtlasCreator { // Select the tile creator instance based on whether tile image // parameters has been set or not - if (parameters != null) + if (parameters != null) { createCustomTiles(); - else + } else { createTiles(); + } mapTileWriter.finalizeMap(); } catch (MapCreationException e) { @@ -130,8 +127,7 @@ public class Maplorer extends AtlasCreator { if (sourceTileData != null) { mapTileWriter.writeTile(tilex, tiley, tileType, sourceTileData); } else { - log.trace(String.format("Tile x=%d y=%d not found in tile archive - creating default", tilex, - tiley)); + log.trace("Tile x={} y={} not found in tile archive - creating default", tilex, tiley); mapTileWriter.writeTile(tilex, tiley, tileType, emptyTileData); } } catch (IOException e) { @@ -147,17 +143,20 @@ public class Maplorer extends AtlasCreator { File setFolder; - int tileHeight = 256; - int tileWidth = 256; + final int tileHeight; + final int tileWidth; public FileTileWriter() throws IOException { super(); setFolder = mapFolder; // don't need an extra sub folder for MAPLORER maps - log.debug("Writing tiles to set folder: " + setFolder); + log.debug("Writing tiles to set folder: {}", setFolder); if (parameters != null) { tileHeight = parameters.getHeight(); tileWidth = parameters.getWidth(); + } else { + tileHeight = 256; + tileWidth = 256; } } @@ -165,11 +164,8 @@ public class Maplorer extends AtlasCreator { String tileFileName = String.format(FILENAME_PATTERN, IntToLetter(tilex + 1), tiley + 1, imageFormat); File f = new File(setFolder, tileFileName); - FileOutputStream out = new FileOutputStream(f); - try { + try (FileOutputStream out = new FileOutputStream(f)) { out.write(tileData); - } finally { - Utilities.closeStream(out); } tileXmax = tilex; @@ -177,8 +173,9 @@ public class Maplorer extends AtlasCreator { } private String IntToLetter(int i) throws IOException { - if (i > 26) + if (i > 26) { throw new IOException("Maximum tile column overflow - map too wide!"); + } char c = (char) (i + 64); return Character.toString(c); } @@ -219,24 +216,18 @@ public class Maplorer extends AtlasCreator { lonTR = Math.min(longitudeMax, lonTR); latTR = Math.min(latitudeMax, latTR); - FileWriter outFile = new FileWriter(posFile); - try { - PrintWriter out2 = new PrintWriter(outFile); - + try (PrintWriter writer = new PrintWriter(new FileWriter(posFile))) { String posLine = "LonBL = %2.6f"; - out2.println(String.format(Locale.ENGLISH, posLine, lonBL)); + writer.println(String.format(Locale.ENGLISH, posLine, lonBL)); posLine = "LatBL = %2.6f"; - out2.println(String.format(Locale.ENGLISH, posLine, latBL)); + writer.println(String.format(Locale.ENGLISH, posLine, latBL)); posLine = "LonTR = %2.6f"; - out2.println(String.format(Locale.ENGLISH, posLine, lonTR)); + writer.println(String.format(Locale.ENGLISH, posLine, lonTR)); posLine = "LatTR = %2.6f"; - out2.println(String.format(Locale.ENGLISH, posLine, latTR)); - out2.close(); - } finally { - Utilities.closeWriter(outFile); + writer.println(String.format(Locale.ENGLISH, posLine, latTR)); } latBL = latBL - tileHeight * pix2latitude; diff --git a/src/main/java/mobac/program/atlascreators/Maverick.java b/mobac/src/main/java/mobac/program/atlascreators/Maverick.java similarity index 76% rename from src/main/java/mobac/program/atlascreators/Maverick.java rename to mobac/src/main/java/mobac/program/atlascreators/Maverick.java index 05faf1a..4495de9 100644 --- a/src/main/java/mobac/program/atlascreators/Maverick.java +++ b/mobac/src/main/java/mobac/program/atlascreators/Maverick.java @@ -1,30 +1,31 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; import mobac.program.annotations.AtlasCreatorName; /** - * Creates maps using the Maverick atlas format (Android - * application). - * + * Creates maps using the + * Maverick atlas format + * (Android application). + *

      * Map/Atlas format see http://help.codesector.com/MapsCache */ -@AtlasCreatorName("Maverick atlas format") +@AtlasCreatorName("Maverick SQLite atlas format") public class Maverick extends RMapsSQLite { public Maverick() { diff --git a/src/main/java/mobac/mapsources/impl/DebugLocalMapSource.java b/mobac/src/main/java/mobac/program/atlascreators/MaverickOld.java similarity index 57% rename from src/main/java/mobac/mapsources/impl/DebugLocalMapSource.java rename to mobac/src/main/java/mobac/program/atlascreators/MaverickOld.java index 5d36f5b..f79466a 100644 --- a/src/main/java/mobac/mapsources/impl/DebugLocalMapSource.java +++ b/mobac/src/main/java/mobac/program/atlascreators/MaverickOld.java @@ -1,42 +1,36 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ -package mobac.mapsources.impl; +package mobac.program.atlascreators; -import mobac.program.interfaces.FileBasedMapSource; +import mobac.program.annotations.AtlasCreatorName; /** - * A {@link FileBasedMapSource} for debugging and testing purposes + * Creates maps using the + * Maverick atlas format + * (Android application). + *

      + * Map/Atlas format see http://help.codesector.com/MapsCache */ -public class DebugLocalMapSource extends DebugMapSource implements FileBasedMapSource { +@AtlasCreatorName("Maverick simple tiles atlas format") +public class MaverickOld extends OSMTracker { - public void initialize() { - } - - public void reinitialize() { - } - - @Override - public String getName() { - return "DebugLocal"; - } - - @Override - public String toString() { - return "Debug (local)"; + public MaverickOld() { + super(); + tileFileNamePattern = "%d/%d/%d.jpg.tile"; } } diff --git a/src/main/java/mobac/program/atlascreators/MobileTrailExplorer.java b/mobac/src/main/java/mobac/program/atlascreators/MobileTrailExplorer.java similarity index 86% rename from src/main/java/mobac/program/atlascreators/MobileTrailExplorer.java rename to mobac/src/main/java/mobac/program/atlascreators/MobileTrailExplorer.java index 9aebbc5..527a654 100644 --- a/src/main/java/mobac/program/atlascreators/MobileTrailExplorer.java +++ b/mobac/src/main/java/mobac/program/atlascreators/MobileTrailExplorer.java @@ -1,27 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; - -import javax.imageio.ImageIO; - import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; import mobac.program.annotations.AtlasCreatorName; @@ -33,21 +27,26 @@ import mobac.program.model.TileImageFormat; import mobac.program.model.TileImageType; import mobac.utilities.Utilities; +import javax.imageio.ImageIO; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + /** - * Creates maps using the Mobile Trail Explorer (MTE) / JTileDownloader atlas format (converted to PNG, size 256x256 - * pixel). - * - * Please note that this atlas format ignores the defined atlas structure. It uses a separate directory for each used - * map source and inside one directory for each zoom level. + * Creates maps using the Mobile Trail Explorer (MTE) / JTileDownloader atlas + * format (converted to PNG, size 256x256 pixel). + *

      + * Please note that this atlas format ignores the defined atlas structure. It + * uses a separate directory for each used map source and inside one directory + * for each zoom level. */ @AtlasCreatorName(value = "Mobile Trail Explorer", type = "MTE") public class MobileTrailExplorer extends AtlasCreator { + protected String appendFileExt = ""; private File mapDir = null; private File mapZoomDir = null; - protected String appendFileExt = ""; - @Override public boolean testMapSource(MapSource mapSource) { return MercatorPower2MapSpace.INSTANCE_256.equals(mapSource.getMapSpace()); @@ -68,9 +67,10 @@ public class MobileTrailExplorer extends AtlasCreator { } catch (IOException e1) { throw new MapCreationException(map, e1); } - if (mapSource.getTileImageType() != TileImageType.PNG) + if (mapSource.getTileImageType() != TileImageType.PNG) { // If the tile image format is not png we have to convert it mapDlTileProvider = new ConvertedRawTileProvider(mapDlTileProvider, TileImageFormat.PNG); + } createTiles(); } @@ -93,11 +93,8 @@ public class MobileTrailExplorer extends AtlasCreator { byte[] sourceTileData = mapDlTileProvider.getTileData(x, y); if (sourceTileData != null) { File f = new File(mapZoomDir, tileFileName); - FileOutputStream out = new FileOutputStream(f); - try { + try (FileOutputStream out = new FileOutputStream(f)) { out.write(sourceTileData); - } finally { - Utilities.closeStream(out); } } } catch (IOException e) { diff --git a/src/main/java/mobac/program/atlascreators/MobileTrailExplorerCache.java b/mobac/src/main/java/mobac/program/atlascreators/MobileTrailExplorerCache.java similarity index 91% rename from src/main/java/mobac/program/atlascreators/MobileTrailExplorerCache.java rename to mobac/src/main/java/mobac/program/atlascreators/MobileTrailExplorerCache.java index 76ab203..6319bdf 100644 --- a/src/main/java/mobac/program/atlascreators/MobileTrailExplorerCache.java +++ b/mobac/src/main/java/mobac/program/atlascreators/MobileTrailExplorerCache.java @@ -1,32 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.BufferedOutputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.HashSet; -import java.util.Set; - -import javax.imageio.ImageIO; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; @@ -40,11 +29,20 @@ import mobac.program.model.TileImageFormat; import mobac.program.model.TileImageType; import mobac.utilities.Utilities; +import javax.imageio.ImageIO; +import java.io.BufferedOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.HashSet; +import java.util.Set; + /** * Creates maps using the Mobile Trail Explorer (MTE) cache format. - * + *

      * Please note that this atlas format ignores the defined atlas structure. - * */ @AtlasCreatorName(value = "Mobile Trail Explorer Cache", type = "MTECache") public class MobileTrailExplorerCache extends AtlasCreator { @@ -59,8 +57,8 @@ public class MobileTrailExplorerCache extends AtlasCreator { } @Override - public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) throws IOException, InterruptedException, - AtlasTestException { + public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) + throws IOException, InterruptedException, AtlasTestException { super.startAtlasCreation(atlas, customAtlasDir); File cacheFile = new File(atlasDir, "MTEFileCache"); OutputStream out = new BufferedOutputStream(new FileOutputStream(cacheFile), 8216); @@ -69,7 +67,7 @@ public class MobileTrailExplorerCache extends AtlasCreator { @Override public void abortAtlasCreation() throws IOException { - Utilities.closeStream(cacheOutStream); + Utilities.closeQuietly(cacheOutStream); super.abortAtlasCreation(); } @@ -85,9 +83,10 @@ public class MobileTrailExplorerCache extends AtlasCreator { } public void createMap() throws MapCreationException, InterruptedException { - if (mapSource.getTileImageType() != TileImageType.PNG) + if (mapSource.getTileImageType() != TileImageType.PNG) { // If the tile image format is not png we have to convert it mapDlTileProvider = new ConvertedRawTileProvider(mapDlTileProvider, TileImageFormat.PNG); + } createTiles(); } @@ -102,8 +101,9 @@ public class MobileTrailExplorerCache extends AtlasCreator { atlasProgress.incMapCreationProgress(); try { byte[] sourceTileData = mapDlTileProvider.getTileData(x, y); - if (sourceTileData != null) + if (sourceTileData != null) { writeTile(mapName, sourceTileData, x, y, zoom); + } } catch (IOException e) { throw new MapCreationException("Error writing tile image: " + e.getMessage(), map, e); } diff --git a/src/main/java/mobac/program/atlascreators/NFComPass.java b/mobac/src/main/java/mobac/program/atlascreators/NFComPass.java similarity index 79% rename from src/main/java/mobac/program/atlascreators/NFComPass.java rename to mobac/src/main/java/mobac/program/atlascreators/NFComPass.java index 980aae6..431faf6 100644 --- a/src/main/java/mobac/program/atlascreators/NFComPass.java +++ b/mobac/src/main/java/mobac/program/atlascreators/NFComPass.java @@ -1,28 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.Writer; - import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; import mobac.program.annotations.AtlasCreatorName; @@ -39,11 +32,18 @@ import mobac.program.interfaces.MapSpace.ProjectionCategory; import mobac.program.model.TileImageFormat; import mobac.program.model.TileImageParameters; import mobac.program.model.TileImageParameters.Name; -import mobac.program.tiledatawriter.TileImagePngDataWriter; +import mobac.program.tiledatawriter.TileImagePngDataWriterBuilder; import mobac.utilities.Utilities; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; + @AtlasCreatorName(value = "nfComPass") -@SupportedParameters(names = { Name.height, Name.width }) +@SupportedParameters(names = {Name.height, Name.width}) public class NFComPass extends AtlasCreator { private File layerDir; @@ -63,25 +63,26 @@ public class NFComPass extends AtlasCreator { @Override public boolean testMapSource(MapSource mapSource) { MapSpace mapSpace = mapSource.getMapSpace(); - return (mapSpace instanceof MercatorPower2MapSpace && ProjectionCategory.SPHERE.equals(mapSpace - .getProjectionCategory())); + return (mapSpace instanceof MercatorPower2MapSpace + && ProjectionCategory.SPHERE.equals(mapSpace.getProjectionCategory())); } @Override public void initLayerCreation(LayerInterface layer) throws IOException { super.initLayerCreation(layer); - if (layer.getMapCount() == 0) + if (layer.getMapCount() == 0) { return; + } int lastZoom = layer.getMap(0).getZoom(); - Writer w = new BufferedWriter(new FileWriter(new File(atlasDir, "nfComPass.dat"), true)); - w.append("[" + layer.getName() + "]\r\n"); - w.append("SIZEXY = extern\r\n"); - w.append("MAPPATH =\r\n"); - w.append("VMAX = 160\r\n"); - w.append("WIDTH = 5\r\n"); - w.append("LASTZOOM = " + lastZoom + "\r\n\r\n"); - w.flush(); - w.close(); + File datFile = new File(atlasDir, "nfComPass.dat"); + try (Writer w = new BufferedWriter(new FileWriter(datFile, true))) { + w.append("[" + layer.getName() + "]\r\n"); + w.append("SIZEXY = extern\r\n"); + w.append("MAPPATH =\r\n"); + w.append("VMAX = 160\r\n"); + w.append("WIDTH = 5\r\n"); + w.append("LASTZOOM = " + lastZoom + "\r\n\r\n"); + } } @Override @@ -92,22 +93,18 @@ public class NFComPass extends AtlasCreator { throw new MapCreationException(map, e); } createKalFile(map); - CacheTileProvider ctp = new CacheTileProvider(mapDlTileProvider); - try { + try (CacheTileProvider ctp = new CacheTileProvider(mapDlTileProvider)) { mapDlTileProvider = ctp; - MapTileBuilder mapTileBuilder = new MapTileBuilder(this, new TileImagePngDataWriter(), + MapTileBuilder mapTileBuilder = new MapTileBuilder(this, new TileImagePngDataWriterBuilder(), new NFCompassTileWriter(), true); atlasProgress.initMapCreation(mapTileBuilder.getCustomTileCount()); mapTileBuilder.createTiles(); - } finally { - ctp.cleanup(); } } protected void createKalFile(MapInterface map) throws MapCreationException { - Writer w = null; MapSpace mapSpace = map.getMapSource().getMapSpace(); double longitudeMin = mapSpace.cXToLon(xMin * tileSize, zoom); double longitudeMax = mapSpace.cXToLon((xMax + 1) * tileSize - 1, zoom); @@ -117,8 +114,8 @@ public class NFComPass extends AtlasCreator { int width = (xMax - xMin + 1) * tileSize; int height = (yMax - yMin + 1) * tileSize; - try { - w = new BufferedWriter(new FileWriter(new File(mapDir, map.getName() + ".kal"), true)); + File kalFile = new File(mapDir, map.getName() + ".kal"); + try (Writer w = new BufferedWriter(new FileWriter(kalFile, true))) { w.append("[" + map.getName() + "]\r\n"); w.append(String.format("TILEXY = %dx%d\r\n", parameters.getWidth(), parameters.getHeight())); w.append("X0LON = " + longitudeMin + "\r\n"); @@ -126,11 +123,8 @@ public class NFComPass extends AtlasCreator { w.append("X1LON = " + longitudeMax + "\r\n"); w.append("Y1LAT = " + latitudeMin + "\r\n"); w.append(String.format("SIZEXY = %dx%d\r\n", width, height)); - w.flush(); } catch (IOException e) { throw new MapCreationException(map, e); - } finally { - Utilities.closeWriter(w); } } @@ -164,11 +158,8 @@ public class NFComPass extends AtlasCreator { File folder = new File(mapDir, folderName); Utilities.mkDir(folder); File f = new File(folder, tileFileName); - FileOutputStream out = new FileOutputStream(f); - try { + try (FileOutputStream out = new FileOutputStream(f)) { out.write(tileData); - } finally { - Utilities.closeStream(out); } } diff --git a/src/main/java/mobac/program/atlascreators/NaviComputer.java b/mobac/src/main/java/mobac/program/atlascreators/NaviComputer.java similarity index 83% rename from src/main/java/mobac/program/atlascreators/NaviComputer.java rename to mobac/src/main/java/mobac/program/atlascreators/NaviComputer.java index 3f296fe..1f03965 100644 --- a/src/main/java/mobac/program/atlascreators/NaviComputer.java +++ b/mobac/src/main/java/mobac/program/atlascreators/NaviComputer.java @@ -1,32 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.IOException; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.text.SimpleDateFormat; -import java.util.Date; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; @@ -41,44 +30,44 @@ import mobac.program.model.TileImageParameters.Name; import mobac.utilities.Utilities; import mobac.utilities.jdbc.SQLiteLoader; +import java.io.File; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.text.SimpleDateFormat; +import java.util.Date; + @AtlasCreatorName("NaviComputer (NMAP)") -@SupportedParameters(names = { Name.format }) +@SupportedParameters(names = {Name.format}) public class NaviComputer extends AtlasCreator implements RequiresSQLite { private static final String NAVI_TABLES = "CREATE TABLE MapInfo (MapType TEXT, Zoom INTEGER NOT NULL, MinX INTEGER, MaxX INTEGER, MinY INTEGER, MaxY INTEGER);\n" + "CREATE TABLE Tiles (id INTEGER NOT NULL PRIMARY KEY, X INTEGER NOT NULL, Y INTEGER NOT NULL, Zoom INTEGER NOT NULL);\n" + "CREATE TABLE TilesData (id INTEGER NOT NULL PRIMARY KEY CONSTRAINT fk_Tiles_id REFERENCES Tiles(id) ON DELETE CASCADE, Tile BLOB NULL);\n" - + "CREATE TRIGGER fkdc_TilesData_id_Tiles_id " - + "BEFORE DELETE ON Tiles " - + "FOR EACH ROW BEGIN " - + "DELETE FROM TilesData WHERE TilesData.id = OLD.id; " - + "END;\n" - + "CREATE TRIGGER fki_TilesData_id_Tiles_id " - + "BEFORE INSERT ON [TilesData] " - + "FOR EACH ROW BEGIN " + + "CREATE TRIGGER fkdc_TilesData_id_Tiles_id " + "BEFORE DELETE ON Tiles " + "FOR EACH ROW BEGIN " + + "DELETE FROM TilesData WHERE TilesData.id = OLD.id; " + "END;\n" + + "CREATE TRIGGER fki_TilesData_id_Tiles_id " + "BEFORE INSERT ON [TilesData] " + "FOR EACH ROW BEGIN " + "SELECT RAISE(ROLLBACK, 'insert on table TilesData violates foreign key constraint fki_TilesData_id_Tiles_id') " - + "WHERE (SELECT id FROM Tiles WHERE id = NEW.id) IS NULL; " - + "END;\n" - + "CREATE TRIGGER fku_TilesData_id_Tiles_id " - + "BEFORE UPDATE ON [TilesData] " - + "FOR EACH ROW BEGIN " + + "WHERE (SELECT id FROM Tiles WHERE id = NEW.id) IS NULL; " + "END;\n" + + "CREATE TRIGGER fku_TilesData_id_Tiles_id " + "BEFORE UPDATE ON [TilesData] " + "FOR EACH ROW BEGIN " + "SELECT RAISE(ROLLBACK, 'update on table TilesData violates foreign key constraint fku_TilesData_id_Tiles_id') " - + "WHERE (SELECT id FROM Tiles WHERE id = NEW.id) IS NULL; " - + "END;\n" + + "WHERE (SELECT id FROM Tiles WHERE id = NEW.id) IS NULL; " + "END;\n" + "CREATE INDEX IndexOfTiles ON Tiles (X, Y, Zoom);"; private static final String INSERT_TILES = "INSERT INTO Tiles (id,X,Y,Zoom) VALUES (?,?,?,?)"; private static final String INSERT_TILES_DATA = "INSERT INTO TilesData (id,Tile) VALUES (?,?)"; private static final String INSERT_MAP_INFO = "INSERT INTO MapInfo (MapType,Zoom,MinX,MaxX,MinY,MaxY) " + "SELECT ?,Min(Zoom),Min(x),Max(x),Min(y),Max(y) FROM Tiles WHERE Zoom=?;"; - - private String databaseFile; - private int wmsTileCount = 1; - private static final int COMMIT_RATE = 100; - private int tileCommitCounter = 0; protected Connection conn = null; + private File databaseFile; + private int wmsTileCount = 1; + private int tileCommitCounter = 0; private PreparedStatement prepTilesData = null, prepTiles = null; @Override @@ -92,10 +81,11 @@ public class NaviComputer extends AtlasCreator implements RequiresSQLite { } @Override - public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) throws IOException, AtlasTestException, - InterruptedException { - if (customAtlasDir == null) + public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) + throws IOException, AtlasTestException, InterruptedException { + if (customAtlasDir == null) { customAtlasDir = Settings.getInstance().getAtlasOutputDirectory(); + } super.startAtlasCreation(atlas, customAtlasDir); databaseFile = getDatabaseFileName(); @@ -122,16 +112,17 @@ public class NaviComputer extends AtlasCreator implements RequiresSQLite { @Override public void createMap() throws MapCreationException, InterruptedException { - if (parameters != null) + if (parameters != null) { mapDlTileProvider = new ConvertedRawTileProvider(mapDlTileProvider, parameters.getFormat()); + } createTiles(); } - private void openConnection() throws SQLException { + private void openConnection() throws SQLException, IOException { if (conn == null || conn.isClosed()) { - String url = "jdbc:sqlite:/" + this.databaseFile; + String url = "jdbc:sqlite:" + databaseFile.getCanonicalPath(); conn = DriverManager.getConnection(url); } } @@ -170,8 +161,9 @@ public class NaviComputer extends AtlasCreator implements RequiresSQLite { protected void initializeDB() throws SQLException { Statement stat = conn.createStatement(); String[] sqlList = NAVI_TABLES.split("\\n"); - for (String sql : sqlList) + for (String sql : sqlList) { stat.addBatch(sql); + } stat.executeBatch(); stat.close(); log.debug("Database initialization complete: tables, trigges and index created"); @@ -226,10 +218,9 @@ public class NaviComputer extends AtlasCreator implements RequiresSQLite { prepTilesData.execute(); } - protected String getDatabaseFileName() { + protected File getDatabaseFileName() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HHmmss_"); - databaseFile = new File(atlasDir, sdf.format(new Date()) + atlas.getName() + ".nmap").getAbsolutePath(); - return databaseFile; + return new File(atlasDir, sdf.format(new Date()) + atlas.getName() + ".nmap"); } } diff --git a/src/main/java/mobac/program/atlascreators/OSMAND.java b/mobac/src/main/java/mobac/program/atlascreators/OSMAND.java similarity index 82% rename from src/main/java/mobac/program/atlascreators/OSMAND.java rename to mobac/src/main/java/mobac/program/atlascreators/OSMAND.java index 58defc9..6db89bf 100644 --- a/src/main/java/mobac/program/atlascreators/OSMAND.java +++ b/mobac/src/main/java/mobac/program/atlascreators/OSMAND.java @@ -1,27 +1,27 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; import mobac.program.annotations.AtlasCreatorName; -@AtlasCreatorName("OSMAND tile storage") +@AtlasCreatorName(value = "OsmAnd tile storage") public class OSMAND extends OSMTracker { public OSMAND() { super(); - tileFileNamePattern += ".tile"; + tileFileNamePattern = "%d/%d/%d%s.tile"; } } diff --git a/src/main/java/mobac/program/atlascreators/OSMAND_SQlite.java b/mobac/src/main/java/mobac/program/atlascreators/OSMAND_SQLite.java similarity index 82% rename from src/main/java/mobac/program/atlascreators/OSMAND_SQlite.java rename to mobac/src/main/java/mobac/program/atlascreators/OSMAND_SQLite.java index 291de6e..f8fa4ca 100644 --- a/src/main/java/mobac/program/atlascreators/OSMAND_SQlite.java +++ b/mobac/src/main/java/mobac/program/atlascreators/OSMAND_SQLite.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; @@ -20,8 +20,8 @@ import mobac.mapsources.mapspace.MercatorPower2MapSpace; import mobac.program.annotations.AtlasCreatorName; import mobac.program.interfaces.MapSource; -@AtlasCreatorName(value = "OSMAND SQLite", type = "OSMAND_SQlite") -public class OSMAND_SQlite extends RMapsSQLite { +@AtlasCreatorName(value = "OsmAnd SQLite", type = "OSMAND_SQLite") +public class OSMAND_SQLite extends RMapsSQLite { @Override public boolean testMapSource(MapSource mapSource) { diff --git a/src/main/java/mobac/program/atlascreators/OSMTracker.java b/mobac/src/main/java/mobac/program/atlascreators/OSMTracker.java similarity index 87% rename from src/main/java/mobac/program/atlascreators/OSMTracker.java rename to mobac/src/main/java/mobac/program/atlascreators/OSMTracker.java index fb9eb01..1f8370c 100644 --- a/src/main/java/mobac/program/atlascreators/OSMTracker.java +++ b/mobac/src/main/java/mobac/program/atlascreators/OSMTracker.java @@ -1,27 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; - -import javax.imageio.ImageIO; - import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; import mobac.program.annotations.AtlasCreatorName; @@ -34,14 +28,20 @@ import mobac.program.interfaces.MapSource; import mobac.program.model.TileImageParameters.Name; import mobac.utilities.Utilities; +import javax.imageio.ImageIO; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + /** * Creates maps identical to the atlas format used by OSMTracker. - * - * Please note that this atlas format ignores the defined atlas structure. It uses a separate directory for each used - * map source and inside one directory for each zoom level. + *

      + * Please note that this atlas format ignores the defined atlas structure. It + * uses a separate directory for each used map source and inside one directory + * for each zoom level. */ @AtlasCreatorName("OSMTracker tile storage") -@SupportedParameters(names = { Name.format }) +@SupportedParameters(names = {Name.format}) public class OSMTracker extends AtlasCreator { protected String tileFileNamePattern = "%d/%d/%d.%s"; @@ -70,8 +70,9 @@ public class OSMTracker extends AtlasCreator { public void createMap() throws MapCreationException, InterruptedException { // This means there should not be any resizing of the tiles. - if (mapTileWriter == null) + if (mapTileWriter == null) { mapTileWriter = new OSMTileWriter(); + } createTiles(); } @@ -85,8 +86,9 @@ public class OSMTracker extends AtlasCreator { atlasProgress.incMapCreationProgress(); try { byte[] sourceTileData = mapDlTileProvider.getTileData(x, y); - if (sourceTileData != null) + if (sourceTileData != null) { mapTileWriter.writeTile(x, y, tileType, sourceTileData); + } } catch (IOException e) { throw new MapCreationException("Error writing tile image: " + e.getMessage(), map, e); } @@ -103,11 +105,8 @@ public class OSMTracker extends AtlasCreator { protected void writeTile(File file, byte[] tileData) throws IOException { Utilities.mkDirs(file.getParentFile()); - FileOutputStream out = new FileOutputStream(file); - try { + try (FileOutputStream out = new FileOutputStream(file)) { out.write(tileData); - } finally { - Utilities.closeStream(out); } } diff --git a/src/main/java/mobac/program/atlascreators/OruxMaps.java b/mobac/src/main/java/mobac/program/atlascreators/OruxMaps.java similarity index 76% rename from src/main/java/mobac/program/atlascreators/OruxMaps.java rename to mobac/src/main/java/mobac/program/atlascreators/OruxMaps.java index f572785..b030888 100644 --- a/src/main/java/mobac/program/atlascreators/OruxMaps.java +++ b/mobac/src/main/java/mobac/program/atlascreators/OruxMaps.java @@ -1,29 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.awt.Color; -import java.awt.Graphics2D; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.util.Locale; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; @@ -40,16 +32,25 @@ import mobac.program.interfaces.MapSpace; import mobac.program.model.TileImageFormat; import mobac.program.model.TileImageParameters; import mobac.program.model.TileImageParameters.Name; -import mobac.utilities.Charsets; import mobac.utilities.Utilities; +import java.awt.Color; +import java.awt.Graphics2D; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.util.Locale; + /** * Creates maps using the OruxMaps (Android) atlas format. - * + * * @author orux */ @AtlasCreatorName("OruxMaps") -@SupportedParameters(names = { Name.format }) +@SupportedParameters(names = {Name.format}) public class OruxMaps extends AtlasCreator { // Calibration file extension @@ -57,12 +58,9 @@ public class OruxMaps extends AtlasCreator { // OruxMaps tile size protected static final int TILE_SIZE = 512; - - protected String calVersionCode; - // OruxMaps background color protected static final Color BG_COLOR = new Color(0xcb, 0xd3, 0xf3); - + protected String calVersionCode; // Each layer is a Main map for OruxMaps protected File oruxMapsMainDir; @@ -73,8 +71,9 @@ public class OruxMaps extends AtlasCreator { protected File oruxMapsImagesDir; protected LayerInterface currentLayer; - - // We need to override the map name, All maps must have the same prefix (layer name) + + // We need to override the map name, All maps must have the same prefix (layer + // name) protected String mapName; public OruxMaps() { @@ -87,33 +86,33 @@ public class OruxMaps extends AtlasCreator { return (mapSource.getMapSpace() instanceof MercatorPower2MapSpace); } - + @Override protected void testAtlas() throws AtlasTestException { - + for (LayerInterface layer : atlas) { int cont = layer.getMapCount(); - for (int i = 0; i < cont; i++){ + for (int i = 0; i < cont; i++) { MapInterface currMap = layer.getMap(i); int currZoomLevel = currMap.getZoom(); - for (int j = i + 1; j < cont; j++){ + for (int j = i + 1; j < cont; j++) { MapInterface nextMap = layer.getMap(j); int nextZoomLevel = nextMap.getZoom(); - if (currZoomLevel == nextZoomLevel) + if (currZoomLevel == nextZoomLevel) { throw new AtlasTestException( - "Unable to create a map with more than a layer with the same zoom level: " + - currMap + " & " + nextMap + - "\nPossible causes:\n" + - "You are combining several layers (using drag & drop in 'Atlas Content')\n" + - "You are creating a large map, and you have not selected the maximum value in 'Settings - Map size'"); - } + "Unable to create a map with more than a layer with the same zoom level: " + currMap + + " & " + nextMap + "\nPossible causes:\n" + + "You are combining several layers (using drag & drop in 'Atlas Content')\n" + + "You are creating a large map, and you have not selected the maximum value in 'Settings - Map size'"); + } + } } - } + } } - /* - * @see mobac.program.atlascreators.AtlasCreator#initLayerCreation(mobac.program .interfaces.LayerInterface) + * @see mobac.program.atlascreators.AtlasCreator#initLayerCreation(mobac.program + * .interfaces.LayerInterface) */ @Override public void initLayerCreation(LayerInterface layer) throws IOException { @@ -134,19 +133,20 @@ public class OruxMaps extends AtlasCreator { /* * (non-Javadoc) - * - * @see mobac.program.atlascreators.AtlasCreator#initializeMap(mobac.program. interfaces.MapInterface, - * mobac.utilities.tar.TarIndex) + * + * @see mobac.program.atlascreators.AtlasCreator#initializeMap(mobac.program. + * interfaces.MapInterface, mobac.utilities.tar.TarIndex) */ @Override public void initializeMap(MapInterface map, TileProvider mapTileProvider) { super.initializeMap(map, mapTileProvider); // OruxMaps default image format, jpeg90; always TILE_SIZE=512; - if (parameters == null) + if (parameters == null) { parameters = new TileImageParameters(TILE_SIZE, TILE_SIZE, TileImageFormat.JPEG90); - else + } else { parameters = new TileImageParameters(TILE_SIZE, TILE_SIZE, parameters.getFormat()); + } mapName = String.format("%s %02d", currentLayer.getName(), map.getZoom()); } @@ -156,13 +156,11 @@ public class OruxMaps extends AtlasCreator { oruxMapsLayerDir = new File(oruxMapsMainDir, mapName); oruxMapsImagesDir = new File(oruxMapsLayerDir, "set"); try { - Utilities.mkDir(oruxMapsLayerDir); - Utilities.mkDir(oruxMapsImagesDir); + Utilities.mkDirs(oruxMapsImagesDir); writeOtrk2File(); createTiles(); } catch (InterruptedException e) { // User has aborted process - return; } catch (Exception e) { throw new MapCreationException(map, e); } @@ -170,45 +168,40 @@ public class OruxMaps extends AtlasCreator { protected void createTiles() throws InterruptedException, MapCreationException { - CacheTileProvider ctp = new CacheTileProvider(mapDlTileProvider); - try { + try (CacheTileProvider ctp = new CacheTileProvider(mapDlTileProvider)) { mapDlTileProvider = ctp; OruxMapTileBuilder mapTileBuilder = new OruxMapTileBuilder(this, new OruxMapTileWriter()); atlasProgress.initMapCreation(mapTileBuilder.getCustomTileCount()); mapTileBuilder.createTiles(); - } finally { - ctp.cleanup(); } } /** * Main calibration file - * + * * @param name */ private void writeMainOtrk2File(String name) { - OutputStreamWriter writer; - FileOutputStream otrk2FileStream = null; File otrk2 = new File(oruxMapsMainDir, name + ORUXMAPS_EXT); - try { - writer = new OutputStreamWriter(new FileOutputStream(otrk2), Charsets.UTF_8); - writer.append("\n"); - writer.append("\n"); - writer.append("\n"); - writer.append("\n"); - writer.append(appendMapContent()); + StringWriter sw = new StringWriter(); + sw.append("\n"); + sw.append("\n"); + sw.append("\n"); + sw.append("\n"); - writer.append("\n"); - writer.append("\n"); - writer.flush(); + sw.append(appendMapContent()); + + sw.append("\n"); + sw.append("\n"); + + try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(otrk2), StandardCharsets.UTF_8)) { + writer.write(sw.toString()); } catch (IOException e) { log.error("", e); - } finally { - Utilities.closeStream(otrk2FileStream); } } @@ -218,28 +211,20 @@ public class OruxMaps extends AtlasCreator { /** * Main calibration file per layer - * */ protected void writeOtrk2File() { - - FileOutputStream stream = null; - OutputStreamWriter mapWriter; File otrk2File = new File(oruxMapsLayerDir, mapName + ORUXMAPS_EXT); - try { - stream = new FileOutputStream(otrk2File); - mapWriter = new OutputStreamWriter(stream, "UTF8"); - mapWriter.append(prepareOtrk2File()); - mapWriter.flush(); + String data = prepareOtrk2File(); + try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(otrk2File), + StandardCharsets.UTF_8)) { + writer.write(data); } catch (IOException e) { log.error("", e); - } finally { - Utilities.closeStream(stream); } } /** * Main calibration file per layer - * */ protected String prepareOtrk2File() { @@ -249,8 +234,8 @@ public class OruxMaps extends AtlasCreator { double longitudeMax = mapSpace.cXToLon((xMax + 1) * tileSize, zoom); double latitudeMin = mapSpace.cYToLat((yMax + 1) * tileSize, zoom); double latitudeMax = mapSpace.cYToLat(yMin * tileSize, zoom); - mapWriter.append("\n"); + mapWriter.append( + "\n"); mapWriter.append("\n"); mapWriter.append("\n"); @@ -284,7 +269,7 @@ public class OruxMaps extends AtlasCreator { return mapWriter.toString(); } - protected class OruxMapTileBuilder extends MapTileBuilder { + protected static class OruxMapTileBuilder extends MapTileBuilder { public OruxMapTileBuilder(AtlasCreator atlasCreator, MapTileWriter mapTileWriter) { super(atlasCreator, mapTileWriter, false); @@ -302,11 +287,9 @@ public class OruxMaps extends AtlasCreator { public void writeTile(int tilex, int tiley, String tileType, byte[] tileData) throws IOException { String tileFileName = String.format("%s_%d_%d.omc2", mapName, tilex, tiley); - FileOutputStream out = new FileOutputStream(new File(oruxMapsImagesDir, tileFileName)); - try { + File tileFile = new File(oruxMapsImagesDir, tileFileName); + try (FileOutputStream out = new FileOutputStream(tileFile)) { out.write(tileData); - } finally { - Utilities.closeStream(out); } } diff --git a/src/main/java/mobac/program/atlascreators/OruxMapsSqlite.java b/mobac/src/main/java/mobac/program/atlascreators/OruxMapsSqlite.java similarity index 80% rename from src/main/java/mobac/program/atlascreators/OruxMapsSqlite.java rename to mobac/src/main/java/mobac/program/atlascreators/OruxMapsSqlite.java index 5c8f514..ad409ac 100644 --- a/src/main/java/mobac/program/atlascreators/OruxMapsSqlite.java +++ b/mobac/src/main/java/mobac/program/atlascreators/OruxMapsSqlite.java @@ -1,30 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.IOException; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Locale; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.program.annotations.AtlasCreatorName; @@ -35,9 +26,18 @@ import mobac.program.interfaces.LayerInterface; import mobac.program.interfaces.RequiresSQLite; import mobac.utilities.jdbc.SQLiteLoader; +import java.io.File; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Locale; + /** * Creates maps using the OruxMaps (Android) atlas format. - * + * * @author orux Some code based on BigPlanetSql atlascreator */ @AtlasCreatorName("OruxMaps Sqlite") @@ -50,7 +50,7 @@ public class OruxMapsSqlite extends OruxMaps implements RequiresSQLite { private static final String DATABASE_FILENAME = "OruxMapsImages.db"; - private String databaseFile; + private File databaseFile; private Connection conn = null; private PreparedStatement prepStmt; @@ -65,12 +65,14 @@ public class OruxMapsSqlite extends OruxMaps implements RequiresSQLite { /* * (non-Javadoc) - * - * @see mobac.program.atlascreators.AtlasCreator#startAtlasCreation(mobac.program.interfaces.AtlasInterface) + * + * @see + * mobac.program.atlascreators.AtlasCreator#startAtlasCreation(mobac.program. + * interfaces.AtlasInterface) */ @Override - public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) throws AtlasTestException, IOException, - InterruptedException { + public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) + throws AtlasTestException, IOException, InterruptedException { super.startAtlasCreation(atlas, customAtlasDir); try { SQLiteLoader.loadSQLite(); @@ -80,14 +82,15 @@ public class OruxMapsSqlite extends OruxMaps implements RequiresSQLite { } /* - * @see mobac.program.atlascreators.AtlasCreator#initLayerCreation(mobac.program .interfaces.LayerInterface) + * @see mobac.program.atlascreators.AtlasCreator#initLayerCreation(mobac.program + * .interfaces.LayerInterface) */ @Override public void initLayerCreation(LayerInterface layer) throws IOException { super.initLayerCreation(layer); - databaseFile = new File(oruxMapsMainDir, DATABASE_FILENAME).getAbsolutePath(); - log.debug("SQLite Database file: " + databaseFile); + databaseFile = new File(oruxMapsMainDir, DATABASE_FILENAME); + log.debug("SQLite Database file: {}", databaseFile); otrk2MapsContent = new StringBuilder(); try { conn = getConnection(); @@ -113,8 +116,8 @@ public class OruxMapsSqlite extends OruxMaps implements RequiresSQLite { closeConnection(); } - private Connection getConnection() throws SQLException { - String url = "jdbc:sqlite:/" + this.databaseFile; + private Connection getConnection() throws SQLException, IOException { + String url = "jdbc:sqlite:" + databaseFile.getCanonicalPath(); Connection conn = DriverManager.getConnection(url); return conn; } @@ -128,44 +131,40 @@ public class OruxMapsSqlite extends OruxMaps implements RequiresSQLite { } catch (Exception e) { } conn = null; + prepStmt = null; } private void initializeDB() throws SQLException { - - Statement stat = conn.createStatement(); - stat.executeUpdate(TABLE_TILES_DDL); - stat.executeUpdate(INDEX_DDL); - stat.executeUpdate(TABLE_ANDROID_METADATA_DDL); - stat.executeUpdate("INSERT INTO android_metadata VALUES ('" + Locale.getDefault().toString() + "')"); - stat.close(); + try (Statement stat = conn.createStatement()) { + stat.executeUpdate(TABLE_TILES_DDL); + stat.executeUpdate(INDEX_DDL); + stat.executeUpdate(TABLE_ANDROID_METADATA_DDL); + stat.executeUpdate("INSERT INTO android_metadata VALUES ('" + Locale.getDefault().toString() + "')"); + } } @Override public void createMap() throws MapCreationException, InterruptedException { - otrk2MapsContent.append(prepareOtrk2File()); - try { - conn = getConnection(); + this.conn = getConnection(); conn.setAutoCommit(false); prepStmt = conn.prepareStatement(INSERT_SQL); createTiles(); - conn.close(); } catch (InterruptedException e) { // User has aborted process - return; } catch (MapCreationException e) { throw e; } catch (Exception e) { throw new MapCreationException(map, e); + } finally { + closeConnection(); } } @Override protected void createTiles() throws InterruptedException, MapCreationException { - - CacheTileProvider ctp = new CacheTileProvider(mapDlTileProvider); - try { + try (CacheTileProvider ctp = new CacheTileProvider(mapDlTileProvider)) { mapDlTileProvider = ctp; MapTileWriter mtw = new OruxMapTileWriterDB(); OruxMapTileBuilder mapTileBuilder = new OruxMapTileBuilder(this, mtw); @@ -175,8 +174,6 @@ public class OruxMapsSqlite extends OruxMaps implements RequiresSQLite { mtw.finalizeMap(); } catch (IOException e) { throw new MapCreationException(map, e); - } finally { - ctp.cleanup(); } } @@ -187,10 +184,8 @@ public class OruxMapsSqlite extends OruxMaps implements RequiresSQLite { private class OruxMapTileWriterDB implements MapTileWriter { - private static final int MAX_BATCH_SIZE = 1000; - private int tileCounter = 0; - private Runtime r = Runtime.getRuntime(); + private final Runtime r = Runtime.getRuntime(); public void writeTile(int tilex, int tiley, String tileType, byte[] tileData) throws IOException { diff --git a/src/main/java/mobac/program/atlascreators/Osmdroid.java b/mobac/src/main/java/mobac/program/atlascreators/Osmdroid.java similarity index 86% rename from src/main/java/mobac/program/atlascreators/Osmdroid.java rename to mobac/src/main/java/mobac/program/atlascreators/Osmdroid.java index 42e64dd..873181a 100644 --- a/src/main/java/mobac/program/atlascreators/Osmdroid.java +++ b/mobac/src/main/java/mobac/program/atlascreators/Osmdroid.java @@ -1,26 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.program.annotations.AtlasCreatorName; @@ -32,8 +27,12 @@ import mobac.program.model.Settings; import mobac.utilities.Utilities; import mobac.utilities.stream.ZipStoreOutputStream; +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + /** - * * http://sourceforge.net/p/mobac/feature-requests/162/ */ @AtlasCreatorName("Osmdroid ZIP") @@ -47,10 +46,11 @@ public class Osmdroid extends OSMTracker { } @Override - public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) throws AtlasTestException, IOException, - InterruptedException { - if (customAtlasDir == null) + public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) + throws AtlasTestException, IOException, InterruptedException { + if (customAtlasDir == null) { customAtlasDir = Settings.getInstance().getAtlasOutputDirectory(); + } SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HHmmss"); String atlasDirName = atlas.getName() + "_" + sdf.format(new Date()); super.startAtlasCreation(atlas, customAtlasDir); @@ -60,13 +60,13 @@ public class Osmdroid extends OSMTracker { @Override public void abortAtlasCreation() throws IOException { - Utilities.closeStream(zipStream); + Utilities.closeQuietly(zipStream); super.abortAtlasCreation(); } @Override public void finishAtlasCreation() throws IOException, InterruptedException { - Utilities.closeStream(zipStream); + Utilities.closeQuietly(zipStream); super.finishAtlasCreation(); } @@ -74,10 +74,11 @@ public class Osmdroid extends OSMTracker { public void initializeMap(MapInterface map, TileProvider mapTileProvider) { super.initializeMap(map, mapTileProvider); currentMapStoreName = map.getMapSource().getName(); - if (currentMapStoreName.equals("TilesAtHome")) + if (currentMapStoreName.equals("TilesAtHome")) { currentMapStoreName = "Osmarender"; - else if (currentMapStoreName.equals("OSM Cycle Map")) + } else if (currentMapStoreName.equals("OSM Cycle Map")) { currentMapStoreName = "CycleMap"; + } } private class OSMDroidTileWriter implements MapTileWriter { diff --git a/src/main/java/mobac/program/atlascreators/OsmdroidGEMF.java b/mobac/src/main/java/mobac/program/atlascreators/OsmdroidGEMF.java similarity index 78% rename from src/main/java/mobac/program/atlascreators/OsmdroidGEMF.java rename to mobac/src/main/java/mobac/program/atlascreators/OsmdroidGEMF.java index 61eb4d1..d17ebf1 100644 --- a/src/main/java/mobac/program/atlascreators/OsmdroidGEMF.java +++ b/mobac/src/main/java/mobac/program/atlascreators/OsmdroidGEMF.java @@ -1,54 +1,54 @@ -/******************************************************************************* - * Copyright (c) MOBAC developers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ******************************************************************************/ -/** - * - */ -package mobac.program.atlascreators; - -import java.io.File; -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; - -import mobac.program.annotations.AtlasCreatorName; -import mobac.program.atlascreators.impl.gemf.GEMFFileCreator; - -/** - * AtlasCreator implementation to create a GEMF archive file. For details about the format, please see the link in - * {@link GEMFFileCreator}. - * - * @author M. Reiter - * - */ -@AtlasCreatorName("Osmdroid GEMF") -public class OsmdroidGEMF extends OSMTracker { - - private static final String GEMF_FILE_EXTENSION = ".gemf"; - - @Override - public void finishAtlasCreation() throws IOException, InterruptedException { - List tileFolders = new LinkedList(); - tileFolders.add(mapDir); - - String gemfLocation = new File(atlasDir, atlas.getName() + GEMF_FILE_EXTENSION).toString(); - - new GEMFFileCreator(gemfLocation, tileFolders, log); - - super.finishAtlasCreation(); - } - -} \ No newline at end of file +/** + * Copyright (c) MOBAC developers + *

      + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + *

      + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + *

      + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * + */ +package mobac.program.atlascreators; + +import mobac.program.annotations.AtlasCreatorName; +import mobac.program.atlascreators.impl.gemf.GEMFFileCreator; + +import java.io.File; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +/** + * AtlasCreator implementation to create a GEMF archive file. For details about + * the format, please see the link in {@link GEMFFileCreator}. + * + * @author M. Reiter + * + */ +@AtlasCreatorName("Osmdroid GEMF") +public class OsmdroidGEMF extends OSMTracker { + + private static final String GEMF_FILE_EXTENSION = ".gemf"; + + @Override + public void finishAtlasCreation() throws IOException, InterruptedException { + List tileFolders = new LinkedList<>(); + tileFolders.add(mapDir); + + String gemfLocation = new File(atlasDir, atlas.getName() + GEMF_FILE_EXTENSION).toString(); + + new GEMFFileCreator(gemfLocation, tileFolders, log); + + super.finishAtlasCreation(); + } + +} diff --git a/src/main/java/mobac/program/atlascreators/OsmdroidSQLite.java b/mobac/src/main/java/mobac/program/atlascreators/OsmdroidSQLite.java similarity index 92% rename from src/main/java/mobac/program/atlascreators/OsmdroidSQLite.java rename to mobac/src/main/java/mobac/program/atlascreators/OsmdroidSQLite.java index a76d3ef..703ecc7 100644 --- a/src/main/java/mobac/program/atlascreators/OsmdroidSQLite.java +++ b/mobac/src/main/java/mobac/program/atlascreators/OsmdroidSQLite.java @@ -1,157 +1,156 @@ -/******************************************************************************* - * Copyright (c) MOBAC developers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ******************************************************************************/ -package mobac.program.atlascreators; - -import java.io.File; -import java.io.IOException; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.SQLException; -import java.sql.Statement; - -import javax.imageio.ImageIO; - -import mobac.exceptions.AtlasTestException; -import mobac.exceptions.MapCreationException; -import mobac.program.annotations.AtlasCreatorName; -import mobac.program.annotations.SupportedParameters; -import mobac.program.atlascreators.tileprovider.ConvertedRawTileProvider; -import mobac.program.atlascreators.tileprovider.TileProvider; -import mobac.program.interfaces.AtlasInterface; -import mobac.program.interfaces.MapInterface; -import mobac.program.interfaces.MapSource; -import mobac.program.interfaces.MapSpace.ProjectionCategory; -import mobac.program.interfaces.RequiresSQLite; -import mobac.program.model.TileImageParameters.Name; -import mobac.utilities.jdbc.SQLiteLoader; - -/** - * http://sourceforge.net/p/mobac/patches/22/ - */ -@AtlasCreatorName("Osmdroid SQLite") -@SupportedParameters(names = { Name.format }) -public class OsmdroidSQLite extends AtlasCreator implements RequiresSQLite { - - private static final int MAX_BATCH_SIZE = 1000; - - protected Connection conn = null; - - public OsmdroidSQLite() { - super(); - SQLiteLoader.loadSQLiteOrShowError(); - } - - @Override - public boolean testMapSource(MapSource mapSource) { - return mapSource.getMapSpace().getProjectionCategory().equals(ProjectionCategory.SPHERE); - } - - @Override - public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) throws IOException, AtlasTestException, - InterruptedException { - super.startAtlasCreation(atlas, customAtlasDir); - String databaseFile = new File(atlasDir, atlas.getName() + ".sqlite").getAbsolutePath(); - try { - SQLiteLoader.loadSQLite(); - } catch (SQLException e) { - throw new AtlasTestException(SQLiteLoader.getMsgSqliteMissing()); - } - try { - conn = DriverManager.getConnection("jdbc:sqlite:" + databaseFile); - Statement stat = conn.createStatement(); - stat.executeUpdate("CREATE TABLE IF NOT EXISTS tiles (key INTEGER PRIMARY KEY, provider TEXT, tile BLOB)"); - stat.close(); - } catch (SQLException e) { - throw new IOException("Error creating SQL database \"" + databaseFile + "\": " + e.getMessage(), e); - } - log.debug("SQLite Database file: " + databaseFile); - } - - @Override - public void initializeMap(MapInterface map, TileProvider mapTileProvider) { - super.initializeMap(map, mapTileProvider); - if (parameters != null) - mapDlTileProvider = new ConvertedRawTileProvider(mapDlTileProvider, parameters.getFormat()); - } - - @Override - public void createMap() throws MapCreationException, InterruptedException { - try { - String provider = map.getMapSource().getName(); - int maxMapProgress = 2 * (xMax - xMin + 1) * (yMax - yMin + 1); - atlasProgress.initMapCreation(maxMapProgress); - conn.setAutoCommit(false); - int batchTileCount = 0; - - ImageIO.setUseCache(false); - PreparedStatement prep = conn.prepareStatement("INSERT or REPLACE INTO tiles VALUES (?, ?, ?);"); - Runtime r = Runtime.getRuntime(); - long heapMaxSize = r.maxMemory(); - - for (long x = xMin; x <= xMax; x++) - for (long y = yMin; y <= yMax; y++) { - checkUserAbort(); - atlasProgress.incMapCreationProgress(); - byte[] sourceTileData = mapDlTileProvider.getTileData((int) x, (int) y); - if (sourceTileData != null) { - long z = zoom; - long index = (((z << z) + x) << z) + y; - prep.setLong(1, index); - prep.setString(2, provider); - prep.setBytes(3, sourceTileData); - prep.addBatch(); - - long heapAvailable = heapMaxSize - r.totalMemory() + r.freeMemory(); - - if ((heapAvailable < HEAP_MIN) || (batchTileCount >= MAX_BATCH_SIZE)) { - log.trace("Executing batch containing " + batchTileCount + " tiles"); - prep.executeBatch(); - prep.clearBatch(); - System.gc(); - conn.commit(); - atlasProgress.incMapCreationProgress(batchTileCount); - batchTileCount = 0; - } - - } - } - prep.executeBatch(); - conn.setAutoCommit(true); - atlasProgress.setMapCreationProgress(maxMapProgress); - } catch (SQLException e) { - throw new MapCreationException("Error writing tile image: " + e.getMessage(), map, e); - } catch (IOException e) { - throw new MapCreationException("Error writing tile image: " + e.getMessage(), map, e); - } - } - - @Override - public void abortAtlasCreation() throws IOException { - SQLiteLoader.closeConnection(conn); - conn = null; - super.abortAtlasCreation(); - } - - @Override - public void finishAtlasCreation() throws IOException, InterruptedException { - SQLiteLoader.closeConnection(conn); - conn = null; - super.finishAtlasCreation(); - } - -} +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.atlascreators; + +import mobac.exceptions.AtlasTestException; +import mobac.exceptions.MapCreationException; +import mobac.program.annotations.AtlasCreatorName; +import mobac.program.annotations.SupportedParameters; +import mobac.program.atlascreators.tileprovider.ConvertedRawTileProvider; +import mobac.program.atlascreators.tileprovider.TileProvider; +import mobac.program.interfaces.AtlasInterface; +import mobac.program.interfaces.MapInterface; +import mobac.program.interfaces.MapSource; +import mobac.program.interfaces.MapSpace.ProjectionCategory; +import mobac.program.interfaces.RequiresSQLite; +import mobac.program.model.TileImageParameters.Name; +import mobac.utilities.jdbc.SQLiteLoader; + +import javax.imageio.ImageIO; +import java.io.File; +import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * http://sourceforge.net/p/mobac/patches/22/ + */ +@AtlasCreatorName("Osmdroid SQLite") +@SupportedParameters(names = {Name.format}) +public class OsmdroidSQLite extends AtlasCreator implements RequiresSQLite { + + protected Connection conn = null; + + public OsmdroidSQLite() { + super(); + SQLiteLoader.loadSQLiteOrShowError(); + } + + @Override + public boolean testMapSource(MapSource mapSource) { + return mapSource.getMapSpace().getProjectionCategory().equals(ProjectionCategory.SPHERE); + } + + @Override + public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) + throws IOException, AtlasTestException, InterruptedException { + super.startAtlasCreation(atlas, customAtlasDir); + String databaseFile = new File(atlasDir, atlas.getName() + ".sqlite").getAbsolutePath(); + try { + SQLiteLoader.loadSQLite(); + } catch (SQLException e) { + throw new AtlasTestException(SQLiteLoader.getMsgSqliteMissing()); + } + try { + conn = DriverManager.getConnection("jdbc:sqlite:" + databaseFile); + Statement stat = conn.createStatement(); + stat.executeUpdate("CREATE TABLE IF NOT EXISTS tiles (key INTEGER PRIMARY KEY, provider TEXT, tile BLOB)"); + stat.close(); + } catch (SQLException e) { + throw new IOException("Error creating SQL database \"" + databaseFile + "\": " + e.getMessage(), e); + } + log.debug("SQLite Database file: " + databaseFile); + } + + @Override + public void initializeMap(MapInterface map, TileProvider mapTileProvider) { + super.initializeMap(map, mapTileProvider); + if (parameters != null) { + mapDlTileProvider = new ConvertedRawTileProvider(mapDlTileProvider, parameters.getFormat()); + } + } + + @Override + public void createMap() throws MapCreationException, InterruptedException { + try { + String provider = map.getMapSource().getName(); + int maxMapProgress = 2 * (xMax - xMin + 1) * (yMax - yMin + 1); + atlasProgress.initMapCreation(maxMapProgress); + conn.setAutoCommit(false); + int batchTileCount = 0; + + ImageIO.setUseCache(false); + PreparedStatement prep = conn.prepareStatement("INSERT or REPLACE INTO tiles VALUES (?, ?, ?);"); + Runtime r = Runtime.getRuntime(); + long heapMaxSize = r.maxMemory(); + + for (long x = xMin; x <= xMax; x++) { + for (long y = yMin; y <= yMax; y++) { + checkUserAbort(); + atlasProgress.incMapCreationProgress(); + byte[] sourceTileData = mapDlTileProvider.getTileData((int) x, (int) y); + if (sourceTileData != null) { + long z = zoom; + long index = (((z << z) + x) << z) + y; + prep.setLong(1, index); + prep.setString(2, provider); + prep.setBytes(3, sourceTileData); + prep.addBatch(); + + long heapAvailable = heapMaxSize - r.totalMemory() + r.freeMemory(); + + if ((heapAvailable < HEAP_MIN) || (batchTileCount >= MAX_BATCH_SIZE)) { + log.trace("Executing batch containing " + batchTileCount + " tiles"); + prep.executeBatch(); + prep.clearBatch(); + System.gc(); + conn.commit(); + atlasProgress.incMapCreationProgress(batchTileCount); + batchTileCount = 0; + } + + } + } + } + prep.executeBatch(); + conn.setAutoCommit(true); + atlasProgress.setMapCreationProgress(maxMapProgress); + } catch (SQLException e) { + throw new MapCreationException("Error writing tile image: " + e.getMessage(), map, e); + } catch (IOException e) { + throw new MapCreationException("Error writing tile image: " + e.getMessage(), map, e); + } + } + + @Override + public void abortAtlasCreation() throws IOException { + SQLiteLoader.closeConnection(conn); + conn = null; + super.abortAtlasCreation(); + } + + @Override + public void finishAtlasCreation() throws IOException, InterruptedException { + SQLiteLoader.closeConnection(conn); + conn = null; + super.finishAtlasCreation(); + } + +} diff --git a/src/main/java/mobac/program/atlascreators/Ozi.java b/mobac/src/main/java/mobac/program/atlascreators/Ozi.java similarity index 88% rename from src/main/java/mobac/program/atlascreators/Ozi.java rename to mobac/src/main/java/mobac/program/atlascreators/Ozi.java index 006030c..0dcbad5 100644 --- a/src/main/java/mobac/program/atlascreators/Ozi.java +++ b/mobac/src/main/java/mobac/program/atlascreators/Ozi.java @@ -1,33 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.util.Locale; - -import javax.imageio.ImageIO; - import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; import mobac.program.annotations.AtlasCreatorName; @@ -41,6 +29,17 @@ import mobac.utilities.Utilities; import mobac.utilities.geo.GeoUtils; import mobac.utilities.imageio.PngXxlWriter; +import javax.imageio.ImageIO; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.util.Locale; + @AtlasCreatorName(value = "OziExplorer (PNG & MAP)", type = "OziPng") @SupportedParameters(names = {}) public class Ozi extends AtlasCreator { @@ -51,8 +50,8 @@ public class Ozi extends AtlasCreator { @Override public boolean testMapSource(MapSource mapSource) { MapSpace mapSpace = mapSource.getMapSpace(); - return (mapSpace instanceof MercatorPower2MapSpace && ProjectionCategory.SPHERE.equals(mapSpace - .getProjectionCategory())); + return (mapSpace instanceof MercatorPower2MapSpace + && ProjectionCategory.SPHERE.equals(mapSpace.getProjectionCategory())); // TODO supports Mercator ellipsoid? } @@ -74,14 +73,11 @@ public class Ozi extends AtlasCreator { } protected void writeMapFile() { - FileOutputStream fout = null; - try { - fout = new FileOutputStream(new File(layerDir, mapName + ".map")); + File mapFile = new File(layerDir, mapName + ".map"); + try (FileOutputStream fout = new FileOutputStream(mapFile)) { writeMapFile(map.getName() + ".png", fout); } catch (Exception e) { log.error("", e); - } finally { - Utilities.closeStream(fout); } } @@ -100,11 +96,13 @@ public class Ozi extends AtlasCreator { int height = (yMax - yMin + 1) * tileSize; // Calculate the 100 pixel scale here for MM1B - // Supplied by MrPete, based on suggestion from Des Newman, author of OziExplorer + // Supplied by MrPete, based on suggestion from Des Newman, author of + // OziExplorer // Set latitude to midpoint (maxLat+minLat/2) double midLat = Math.toRadians((latitudeMax + latitudeMin) / 2.0); - // Calculate 50 pixel Longitude for interpolation: Lon50 = 50/(ImagePixelWidth) * abs(maxLon - minLon) + // Calculate 50 pixel Longitude for interpolation: Lon50 = 50/(ImagePixelWidth) + // * abs(maxLon - minLon) double rlonMax = Math.toRadians(longitudeMax); double rlonMin = Math.toRadians(longitudeMin); double Lon50 = (50.0 / width) * Math.abs(rlonMax - rlonMin); @@ -112,18 +110,21 @@ public class Ozi extends AtlasCreator { // Calculate midpoint Lon: midLon = (maxLon+minLon)/2 double midLon = (rlonMax + rlonMin) / 2.0; - // Set lonW and lonE to midpoint +/1 50 pixels: lonW = midLon - Lon50; lonE = midLon+Lon50 + // Set lonW and lonE to midpoint +/1 50 pixels: lonW = midLon - Lon50; lonE = + // midLon+Lon50 double lonW = midLon - Lon50; double lonE = midLon + Lon50; // Now do the calculation: - // d=2*asin(sqrt((sin((lat1-lat2)/2))^2 + cos(lat1)*cos(lat2)*(sin((lon1-lon2)/2))^2)) + // d=2*asin(sqrt((sin((lat1-lat2)/2))^2 + + // cos(lat1)*cos(lat2)*(sin((lon1-lon2)/2))^2)) // d=2*asin(sqrt(0 + cos(lat1)*cos(lat2)*(sin((lon1-lon2)/2))^2)) double mDistA = Math.cos(midLat); double mDistB = Math.sin((lonW - lonE) / 2.0); double mDist = 2.0 * Math.asin(Math.sqrt(mDistA * mDistA * mDistB * mDistB)); - // For the final scaling, convert to distance in meters (multiply by earth radius), + // For the final scaling, convert to distance in meters (multiply by earth + // radius), // then simply divide by 100 (100 pixels between the two reference points) // We're using the polar radius, as this gives results very close to OziExplorer double mm1b = 6399592 * mDist / 100.0; @@ -196,8 +197,8 @@ public class Ozi extends AtlasCreator { } /** - * Writes the large picture (tile) line by line. Each line has the full width of the map and the height of one tile - * (256 pixels). + * Writes the large picture (tile) line by line. Each line has the full width of + * the map and the height of one tile (256 pixels). */ protected void createTiles() throws InterruptedException, MapCreationException { atlasProgress.initMapCreation((xMax - xMin + 1) * (yMax - yMin + 1)); @@ -207,10 +208,8 @@ public class Ozi extends AtlasCreator { int height = (yMax - yMin + 1) * tileSize; int tileLineHeight = tileSize; - FileOutputStream fileOs = null; Color backgroundColor = mapSource.getBackgroundColor(); - try { - fileOs = new FileOutputStream(new File(layerDir, mapName + ".png")); + try (FileOutputStream fileOs = new FileOutputStream(new File(layerDir, mapName + ".png"))) { PngXxlWriter pngWriter = new PngXxlWriter(width, height, fileOs); for (int y = yMin; y <= yMax; y++) { @@ -224,8 +223,9 @@ public class Ozi extends AtlasCreator { checkUserAbort(); atlasProgress.incMapCreationProgress(); BufferedImage tile = mapDlTileProvider.getTileImage(x, y); - if (tile != null) + if (tile != null) { graphics.drawImage(tile, lineX, 0, backgroundColor, null); + } lineX += tileSize; } } finally { @@ -236,8 +236,6 @@ public class Ozi extends AtlasCreator { pngWriter.finish(); } catch (IOException e) { throw new MapCreationException(map, e); - } finally { - Utilities.closeStream(fileOs); } } } diff --git a/src/main/java/mobac/program/atlascreators/PNGWorldfile.java b/mobac/src/main/java/mobac/program/atlascreators/PNGWorldfile.java similarity index 82% rename from src/main/java/mobac/program/atlascreators/PNGWorldfile.java rename to mobac/src/main/java/mobac/program/atlascreators/PNGWorldfile.java index 4386cb2..d02900d 100644 --- a/src/main/java/mobac/program/atlascreators/PNGWorldfile.java +++ b/mobac/src/main/java/mobac/program/atlascreators/PNGWorldfile.java @@ -1,31 +1,32 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; +import mobac.exceptions.MapCreationException; +import mobac.program.annotations.AtlasCreatorName; +import mobac.utilities.Utilities; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; +import java.io.Writer; import java.util.Locale; -import mobac.exceptions.MapCreationException; -import mobac.program.annotations.AtlasCreatorName; -import mobac.utilities.Utilities; - /** * http://sourceforge.net/p/mobac/feature-requests/136/ */ @@ -46,9 +47,9 @@ public class PNGWorldfile extends Glopus { /** * http://en.wikipedia.org/wiki/World_file - * + * *

      -	 * Format of Worldfile: 
      +	 * Format of Worldfile:
       	 * 			   0.000085830078125  (size of pixel in x direction)                              =(east-west)/image width
       	 * 			   0.000000000000     (rotation term for row)
       	 * 			   0.000000000000     (rotation term for column)
      @@ -58,11 +59,8 @@ public class PNGWorldfile extends Glopus {
       	 * 
      */ private void writeWorldFile() throws MapCreationException { - FileOutputStream fout = null; - try { - fout = new FileOutputStream(new File(layerDir, mapName + ".pgw")); - OutputStreamWriter mapWriter = new OutputStreamWriter(fout, TEXT_FILE_CHARSET); - + try (Writer mapWriter = new OutputStreamWriter(new FileOutputStream(new File(layerDir, mapName + ".pgw")), + TEXT_FILE_CHARSET)) { // MapSpace mapSpace = mapSource.getMapSpace(); double worldSize = 2 * Math.PI * 6378137; @@ -81,19 +79,14 @@ public class PNGWorldfile extends Glopus { mapWriter.write(String.format(Locale.ENGLISH, "%.7f\n", yMax1 - 0.5 * pixelSize)); mapWriter.flush(); - mapWriter.close(); } catch (IOException e) { throw new MapCreationException(map, e); - } finally { - Utilities.closeStream(fout); } } private void writeProjectionFile() throws MapCreationException { - FileOutputStream fout = null; - try { - fout = new FileOutputStream(new File(layerDir, mapName + ".png.aux.xml")); - OutputStreamWriter writer = new OutputStreamWriter(fout, TEXT_FILE_CHARSET); + File xmlFile = new File(layerDir, mapName + ".png.aux.xml"); + try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(xmlFile), TEXT_FILE_CHARSET)) { writer.write("PROJCS["WGS 84 / Pseudo-Mercator",GEOGCS["WGS 84"," + "DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563," @@ -104,15 +97,13 @@ public class PNGWorldfile extends Glopus { + "PARAMETER["scale_factor",1],PARAMETER["false_easting",0]," + "PARAMETER["false_northing",0],UNIT["metre",1," + "AUTHORITY["EPSG","9001"]]," - + "EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"]," + + "EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 " + + "+x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"]," + "AUTHORITY["EPSG","3857"]]"); writer.flush(); - writer.close(); } catch (IOException e) { throw new MapCreationException(map, e); - } finally { - Utilities.closeStream(fout); } } } diff --git a/src/main/java/mobac/program/atlascreators/PaperAtlas.java b/mobac/src/main/java/mobac/program/atlascreators/PaperAtlas.java similarity index 93% rename from src/main/java/mobac/program/atlascreators/PaperAtlas.java rename to mobac/src/main/java/mobac/program/atlascreators/PaperAtlas.java index a3291f1..d9211c0 100644 --- a/src/main/java/mobac/program/atlascreators/PaperAtlas.java +++ b/mobac/src/main/java/mobac/program/atlascreators/PaperAtlas.java @@ -1,37 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Image; -import java.awt.Insets; -import java.awt.Point; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; - -import javax.imageio.ImageIO; -import javax.swing.JComponent; -import javax.swing.JPanel; - import mobac.exceptions.MapCreationException; import mobac.gui.mapview.ScaleBar; import mobac.gui.mapview.WgsGrid; @@ -46,37 +30,36 @@ import mobac.program.model.SettingsWgsGrid; import mobac.program.model.UnitSystem; import mobac.utilities.Utilities; +import javax.imageio.ImageIO; +import javax.swing.JComponent; +import javax.swing.JPanel; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Insets; +import java.awt.Point; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + public abstract class PaperAtlas extends AtlasCreator { - private static final Font PAGE_NUMBER_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 24), LABEL_FONT = new Font( - Font.SANS_SERIF, Font.BOLD, 12); + private static final Font PAGE_NUMBER_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 24), + LABEL_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 12); private static final Color LABEL_BACKGROUND = new Color(0, 127, 0), LABEL_FOREGROUND = Color.WHITE, IMAGE_BACKGROUND = new Color(0, 0, 0, 0); private static final String UP = " \u2191", DOWN = " \u2193"; - - protected static class Page { - protected final BufferedImage image; - protected final int number, width, height; - - protected Page(int number, BufferedImage image) { - this.number = number; - this.image = image; - this.width = image.getWidth(); - this.height = image.getHeight(); - } - } - + protected final SettingsPaperAtlas s; private final JComponent dummy = new JPanel(); private final WgsGrid wgsGrid; private final int overlap; private final Insets insets = new Insets(0, 0, 0, 0); - - protected final SettingsPaperAtlas s; - private int tileImageScale = 1; - private File layerFolder; // base: page Size整数倍区域, // bottom:最底下的不能被page Height整除的区域 @@ -166,8 +149,9 @@ public abstract class PaperAtlas extends AtlasCreator { } /** - * check first existing image and return its scale. 2 means for retina( 512x512), 1 means normal - * + * check first existing image and return its scale. 2 means for retina( + * 512x512), 1 means normal + * * @return */ protected int getTileImageScale() { @@ -209,7 +193,7 @@ public abstract class PaperAtlas extends AtlasCreator { atlasProgress.initMapCreation(ROWS * COLS * 2); for (int row = 0; row < ROWS; row++) { for (int col = 0; col < COLS; col++) { - log.trace(String.format("cal=%d row=%d", col, row)); + log.trace("cal={} row={}", col, row); // Choose image Dimension size; @@ -257,20 +241,23 @@ public abstract class PaperAtlas extends AtlasCreator { int x = tileCol * tileSize * tileImageScale; int y = tileRow * tileSize * tileImageScale; BufferedImage tile = mapDlTileProvider.getTileImage(tileX, tileY); - if (tile != null) + if (tile != null) { g.drawImage(tile, x, y, tileSize * tileImageScale, tileSize * tileImageScale, null); + } } } g.translate(firstTileXOffset, firstTileYOffset); // Paint additions dummy.setSize(size); - Point tlc = new Point(firstTileX * tileSize * tileImageScale + firstTileXOffset, firstTileY - * tileSize * tileImageScale + firstTileYOffset); - if (s.wgsEnabled) + Point tlc = new Point(firstTileX * tileSize * tileImageScale + firstTileXOffset, + firstTileY * tileSize * tileImageScale + firstTileYOffset); + if (s.wgsEnabled) { wgsGrid.paintWgsGrid(g, mapSource.getMapSpace(), tlc, zoom); - if (s.scaleBar) + } + if (s.scaleBar) { ScaleBar.paintScaleBar(dummy, g, mapSource.getMapSpace(), tlc, zoom); + } if (s.compass) { Image compassRaw = ImageIO.read(Utilities.loadResourceAsStream("images/compass.png")); Image compass = compassRaw.getScaledInstance(150, 150, Image.SCALE_SMOOTH); @@ -336,4 +323,16 @@ public abstract class PaperAtlas extends AtlasCreator { && (ProjectionCategory.SPHERE.equals(projection) || ProjectionCategory.ELLIPSOID.equals(projection)); } + protected static class Page { + protected final BufferedImage image; + protected final int number, width, height; + + protected Page(int number, BufferedImage image) { + this.number = number; + this.image = image; + this.width = image.getWidth(); + this.height = image.getHeight(); + } + } + } diff --git a/src/main/java/mobac/program/atlascreators/PaperAtlasPdf.java b/mobac/src/main/java/mobac/program/atlascreators/PaperAtlasPdf.java similarity index 94% rename from src/main/java/mobac/program/atlascreators/PaperAtlasPdf.java rename to mobac/src/main/java/mobac/program/atlascreators/PaperAtlasPdf.java index 1668bf1..0666297 100644 --- a/src/main/java/mobac/program/atlascreators/PaperAtlasPdf.java +++ b/mobac/src/main/java/mobac/program/atlascreators/PaperAtlasPdf.java @@ -1,127 +1,126 @@ -/******************************************************************************* - * Copyright (c) MOBAC developers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ******************************************************************************/ -package mobac.program.atlascreators; - -import java.awt.Color; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; - -import mobac.exceptions.MapCreationException; -import mobac.program.ProgramInfo; -import mobac.program.annotations.AtlasCreatorName; -import mobac.program.model.UnitSystem; - -import com.itextpdf.text.BadElementException; -import com.itextpdf.text.Document; -import com.itextpdf.text.DocumentException; -import com.itextpdf.text.Image; -import com.itextpdf.text.Rectangle; -import com.itextpdf.text.pdf.PdfWriter; - -@AtlasCreatorName(value = "Paper Atlas (PDF)") -public class PaperAtlasPdf extends PaperAtlas { - - private Document document; - - public PaperAtlasPdf() { - super(false); - } - - private Document createDocument(Rectangle r) throws MapCreationException { - File pdfFile = new File(getLayerFolder(), map.getName() + ".pdf"); - float left = (float) s.marginLeft; - float right = (float) s.marginRight; - float top = (float) s.marginTop; - float bottom = (float) s.marginBottom; - Document document = new Document(r, left, right, top, bottom); - PdfWriter pdfWriter; - try { - pdfFile.createNewFile(); - pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(pdfFile)); - } catch (IOException e) { - throw new MapCreationException(map, e); - } catch (DocumentException e) { - throw new MapCreationException(map, e); - } - pdfWriter.setCompressionLevel(s.compression); - document.open(); - document.addAuthor(ProgramInfo.PROG_NAME); - document.addCreationDate(); - document.addCreator(ProgramInfo.PROG_NAME); - document.addProducer(); - return document; - } - - @Override - public void createMap() throws MapCreationException, InterruptedException { - - if (s.paperSize != null) { - document = createDocument(s.paperSize.createRectangle()); - } - - try { - super.createMap(); - } finally { - try { - document.close(); - } catch (Exception e) { - new MapCreationException(map, e); - } - document = null; - } - } - - @Override - protected void processPage(BufferedImage image, int pageNumber) throws MapCreationException { - int imageWidth = image.getWidth(); - int imageHeight = image.getHeight(); - - if (document == null) { - double width = UnitSystem.pixelsToPoints(imageWidth, s.dpi); - double height = UnitSystem.pixelsToPoints(imageHeight, s.dpi); - width += s.marginLeft + s.marginRight; - height += s.marginTop + s.marginBottom; - Rectangle r = new Rectangle((float) width, (float) height); - document = createDocument(r); - } - - Image iTextImage; - try { - iTextImage = Image.getInstance(image, Color.WHITE); - } catch (BadElementException e) { - throw new MapCreationException(map, e); - } catch (IOException e) { - throw new MapCreationException(map, e); - } - iTextImage.setCompressionLevel(s.compression); - iTextImage.setDpi(s.dpi, s.dpi); - - float width = (float) UnitSystem.pixelsToPoints(imageWidth, s.dpi); - float height = (float) UnitSystem.pixelsToPoints(imageHeight, s.dpi); - iTextImage.scaleAbsolute(width, height); - - try { - document.add(iTextImage); - } catch (DocumentException e) { - throw new MapCreationException(map, e); - } - document.newPage(); - } - -} +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.atlascreators; + +import com.itextpdf.text.BadElementException; +import com.itextpdf.text.Document; +import com.itextpdf.text.DocumentException; +import com.itextpdf.text.Image; +import com.itextpdf.text.Rectangle; +import com.itextpdf.text.pdf.PdfWriter; +import mobac.exceptions.MapCreationException; +import mobac.program.ProgramInfo; +import mobac.program.annotations.AtlasCreatorName; +import mobac.program.model.UnitSystem; + +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + +@AtlasCreatorName(value = "Paper Atlas (PDF)") +public class PaperAtlasPdf extends PaperAtlas { + + private Document document; + + public PaperAtlasPdf() { + super(false); + } + + private Document createDocument(Rectangle r) throws MapCreationException { + File pdfFile = new File(getLayerFolder(), map.getName() + ".pdf"); + float left = (float) s.marginLeft; + float right = (float) s.marginRight; + float top = (float) s.marginTop; + float bottom = (float) s.marginBottom; + Document document = new Document(r, left, right, top, bottom); + PdfWriter pdfWriter; + try { + pdfFile.createNewFile(); + pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(pdfFile)); + } catch (IOException e) { + throw new MapCreationException(map, e); + } catch (DocumentException e) { + throw new MapCreationException(map, e); + } + pdfWriter.setCompressionLevel(s.compression); + document.open(); + document.addAuthor(ProgramInfo.PROG_NAME); + document.addCreationDate(); + document.addCreator(ProgramInfo.PROG_NAME); + document.addProducer(); + return document; + } + + @Override + public void createMap() throws MapCreationException, InterruptedException { + + if (s.paperSize != null) { + document = createDocument(s.paperSize.createRectangle()); + } + + try { + super.createMap(); + } finally { + try { + document.close(); + } catch (Exception e) { + new MapCreationException(map, e); + } + document = null; + } + } + + @Override + protected void processPage(BufferedImage image, int pageNumber) throws MapCreationException { + int imageWidth = image.getWidth(); + int imageHeight = image.getHeight(); + + if (document == null) { + double width = UnitSystem.pixelsToPoints(imageWidth, s.dpi); + double height = UnitSystem.pixelsToPoints(imageHeight, s.dpi); + width += s.marginLeft + s.marginRight; + height += s.marginTop + s.marginBottom; + Rectangle r = new Rectangle((float) width, (float) height); + document = createDocument(r); + } + + Image iTextImage; + try { + iTextImage = Image.getInstance(image, Color.WHITE); + } catch (BadElementException e) { + throw new MapCreationException(map, e); + } catch (IOException e) { + throw new MapCreationException(map, e); + } + iTextImage.setCompressionLevel(s.compression); + iTextImage.setDpi(s.dpi, s.dpi); + + float width = (float) UnitSystem.pixelsToPoints(imageWidth, s.dpi); + float height = (float) UnitSystem.pixelsToPoints(imageHeight, s.dpi); + iTextImage.scaleAbsolute(width, height); + + try { + document.add(iTextImage); + } catch (DocumentException e) { + throw new MapCreationException(map, e); + } + document.newPage(); + } + +} diff --git a/src/main/java/mobac/program/atlascreators/PaperAtlasPng.java b/mobac/src/main/java/mobac/program/atlascreators/PaperAtlasPng.java similarity index 86% rename from src/main/java/mobac/program/atlascreators/PaperAtlasPng.java rename to mobac/src/main/java/mobac/program/atlascreators/PaperAtlasPng.java index 6b7a1bd..1aec1ba 100644 --- a/src/main/java/mobac/program/atlascreators/PaperAtlasPng.java +++ b/mobac/src/main/java/mobac/program/atlascreators/PaperAtlasPng.java @@ -1,32 +1,31 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.text.DecimalFormat; - -import javax.imageio.ImageIO; - import mobac.exceptions.MapCreationException; import mobac.program.annotations.AtlasCreatorName; import mobac.utilities.Utilities; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.text.DecimalFormat; + @AtlasCreatorName(value = "Paper Atlas (PNG)") public class PaperAtlasPng extends PaperAtlas { @@ -55,7 +54,9 @@ public class PaperAtlasPng extends PaperAtlas { String fileName = decimalFormat.format(pageNumber) + ".png"; File file = new File(mapFolder, fileName); try { - ImageIO.write(image, "PNG", file); + if (!ImageIO.write(image, "PNG", file)) { + throw new MapCreationException(String.format("Failed to write PNG for page %d", pageNumber), map); + } } catch (IOException e) { throw new MapCreationException(map, e); } diff --git a/src/main/java/mobac/program/atlascreators/PathAway.java b/mobac/src/main/java/mobac/program/atlascreators/PathAway.java similarity index 78% rename from src/main/java/mobac/program/atlascreators/PathAway.java rename to mobac/src/main/java/mobac/program/atlascreators/PathAway.java index 58a0011..c64bc6a 100644 --- a/src/main/java/mobac/program/atlascreators/PathAway.java +++ b/mobac/src/main/java/mobac/program/atlascreators/PathAway.java @@ -1,24 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.IOException; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.program.annotations.AtlasCreatorName; @@ -27,9 +24,13 @@ import mobac.program.interfaces.LayerInterface; import mobac.program.interfaces.MapInterface; import mobac.program.interfaces.MapSource; +import java.io.File; +import java.io.IOException; + /** - * Creates a tile cache structure as used by PathAway (for WindowsMobile, - * Symbian, Palm) + * Creates a tile cache structure as used by + * PathAway (for WindowsMobile, Symbian, + * Palm) */ @AtlasCreatorName("PathAway tile cache") public class PathAway extends OSMTracker { @@ -45,24 +46,27 @@ public class PathAway extends OSMTracker { MapSource mapSource = map.getMapSource(); String shortMapDir = null; - if (mapSource.getName().equals("Google Maps")) + if (mapSource.getName().equals("Google Maps")) { shortMapDir = "G1"; - else if (mapSource.getName().equals("Google Earth")) + } else if (mapSource.getName().equals("Google Earth")) { shortMapDir = "G2"; - else if (mapSource.getName().equals("Google Terrain")) + } else if (mapSource.getName().equals("Google Terrain")) { shortMapDir = "G3"; - else if (mapSource.getName().equals("Mapnik")) + } else if (mapSource.getName().equals("Mapnik")) { shortMapDir = "OSM1"; - else if (mapSource.getName().equals("OSM Cycle Map")) + } else if (mapSource.getName().equals("OSM Cycle Map")) { shortMapDir = "OCM1"; - if (shortMapDir != null) + } + if (shortMapDir != null) { mapDir = new File(atlasDir, shortMapDir); + } } public void createMap() throws MapCreationException, InterruptedException { // This means there should not be any resizing of the tiles. - if (mapTileWriter == null) + if (mapTileWriter == null) { mapTileWriter = new PathAwayTileWriter(); + } createTiles(); } @@ -70,8 +74,9 @@ public class PathAway extends OSMTracker { protected void testAtlas() throws AtlasTestException { for (LayerInterface layer : atlas) { for (MapInterface map : layer) { - if (map.getZoom() > 17) + if (map.getZoom() > 17) { throw new AtlasTestException("resolution too high - " + "highest possible zoom level is 17"); + } } } } diff --git a/mobac/src/main/java/mobac/program/atlascreators/RMapsSQLite.java b/mobac/src/main/java/mobac/program/atlascreators/RMapsSQLite.java new file mode 100644 index 0000000..4f5a89b --- /dev/null +++ b/mobac/src/main/java/mobac/program/atlascreators/RMapsSQLite.java @@ -0,0 +1,172 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.atlascreators; + +import mobac.exceptions.AtlasTestException; +import mobac.exceptions.MapCreationException; +import mobac.program.annotations.AtlasCreatorName; +import mobac.program.annotations.SupportedParameters; +import mobac.program.interfaces.AtlasInterface; +import mobac.program.interfaces.MapSource; +import mobac.program.interfaces.MapSpace; +import mobac.program.interfaces.MapSpace.ProjectionCategory; +import mobac.program.model.Settings; +import mobac.program.model.TileImageParameters.Name; +import mobac.utilities.Utilities; + +import java.io.File; +import java.io.IOException; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Locale; + +/** + * Atlas/Map creator for "BigPlanet-Maps application for Android" (offline + * SQLite maps) http://code.google.com/p/bigplanet/ + *

      + * Some source parts are taken from the "android-map.blogspot.com Version of + * Mobile Atlas Creator": http://code.google.com/p/android-map/ + *

      + *

      + * Additionally the created BigPlanet SQLite database has one additional table + * containing special info needed by the Android application + * RMaps.
      + * (Database statements: {@link #RMAPS_TABLE_INFO_DDL} and + * {@link #RMAPS_INSERT_INFO_MINMAX_SQL} ).
      + * Changes made by Robert, author of + * RMaps. + *

      + */ +@AtlasCreatorName(value = "RMaps SQLite", type = "RMaps") +@SupportedParameters(names = {Name.format}) +public class RMapsSQLite extends AbstractSQLite { + + private static final String TABLE_DDL = "CREATE TABLE IF NOT EXISTS tiles (x int, y int, z int, s int, image blob, PRIMARY KEY (x,y,z,s))"; + private static final String INDEX_DDL = "CREATE INDEX IF NOT EXISTS IND on tiles (x,y,z,s)"; + private static final String INSERT_SQL = "INSERT or REPLACE INTO tiles (x,y,z,s,image) VALUES (?,?,?,0,?)"; + private static final String RMAPS_TABLE_INFO_DDL = "CREATE TABLE IF NOT EXISTS info AS SELECT 99 AS minzoom, 0 AS maxzoom"; + private static final String RMAPS_CLEAR_INFO_SQL = "DELETE FROM info;"; + private static final String RMAPS_INSERT_INFO_MINMAX_SQL = "INSERT INTO info (minzoom,maxzoom) VALUES (?,?);"; + private static final String RMAPS_INFO_MAX_SQL = "SELECT DISTINCT z FROM tiles ORDER BY z DESC LIMIT 1;"; + private static final String RMAPS_INFO_MIN_SQL = "SELECT DISTINCT z FROM tiles ORDER BY z ASC LIMIT 1;"; + + public RMapsSQLite() { + super(); + } + + @Override + public boolean testMapSource(MapSource mapSource) { + MapSpace mapSpace = mapSource.getMapSpace(); + boolean correctTileSize = (256 == mapSpace.getTileSize()); + ProjectionCategory pc = mapSpace.getProjectionCategory(); + boolean correctProjection = (ProjectionCategory.SPHERE.equals(pc) || ProjectionCategory.ELLIPSOID.equals(pc)); + return correctTileSize && correctProjection; + } + + @Override + public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) + throws IOException, AtlasTestException, InterruptedException { + if (customAtlasDir == null) { + customAtlasDir = Settings.getInstance().getAtlasOutputDirectory(); + } + super.startAtlasCreation(atlas, customAtlasDir); + } + + @Override + public void createMap() throws MapCreationException, InterruptedException { + try { + Utilities.mkDir(atlasDir); + } catch (IOException e) { + throw new MapCreationException(map, e); + } + try { + openConnection(); + initializeDB(); + createTiles(); + } catch (SQLException | IOException e) { + throw new MapCreationException("Error creating SQL database \"" + databaseFile + "\": " + e.getMessage(), + map, e); + } + } + + protected void initializeDB() throws SQLException { + try (Statement stat = conn.createStatement()) { + stat.executeUpdate(TABLE_DDL); + stat.executeUpdate(INDEX_DDL); + createInfoTable(stat); + + stat.executeUpdate("CREATE TABLE IF NOT EXISTS android_metadata (locale TEXT)"); + if (!(stat.executeQuery("SELECT * FROM android_metadata").next())) { + String locale = Locale.getDefault().toString(); + stat.executeUpdate("INSERT INTO android_metadata VALUES ('" + locale + "')"); + } + } + } + + protected void createInfoTable(Statement stat) throws SQLException { + stat.executeUpdate(RMAPS_TABLE_INFO_DDL); + } + + @Override + protected void updateTileMetaInfo() throws SQLException { + int min, max; + try (Statement stat = conn.createStatement()) { + try (ResultSet rs = stat.executeQuery(RMAPS_INFO_MAX_SQL)) { + if (!rs.next()) { + throw new SQLException("failed to retrieve max tile zoom info"); + } + max = rs.getInt(1); + } + try (ResultSet rs = stat.executeQuery(RMAPS_INFO_MIN_SQL)) { + if (!rs.next()) { + throw new SQLException("failed to retrieve min tile zoom info"); + } + min = rs.getInt(1); + } + stat.execute(RMAPS_CLEAR_INFO_SQL); + try (PreparedStatement ps = conn.prepareStatement(RMAPS_INSERT_INFO_MINMAX_SQL)) { + ps.setInt(1, min); + ps.setInt(2, max); + ps.execute(); + } + } + + } + + @Override + protected void writeTile(int x, int y, int z, byte[] tileData) throws SQLException, IOException { + prepStmt.setInt(1, x); + prepStmt.setInt(2, y); + prepStmt.setInt(3, 17 - z); + prepStmt.setBytes(4, tileData); + prepStmt.addBatch(); + } + + @Override + protected String getDatabaseFileName() { + return atlas.getName() + ".sqlitedb"; + } + + @Override + protected String getTileInsertSQL() { + return INSERT_SQL; + } + +} diff --git a/src/main/java/mobac/program/atlascreators/RunGPSAtlas.java b/mobac/src/main/java/mobac/program/atlascreators/RunGPSAtlas.java similarity index 86% rename from src/main/java/mobac/program/atlascreators/RunGPSAtlas.java rename to mobac/src/main/java/mobac/program/atlascreators/RunGPSAtlas.java index cb18637..70cfea4 100644 --- a/src/main/java/mobac/program/atlascreators/RunGPSAtlas.java +++ b/mobac/src/main/java/mobac/program/atlascreators/RunGPSAtlas.java @@ -1,29 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; - -import javax.imageio.ImageIO; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; @@ -37,16 +29,25 @@ import mobac.program.interfaces.MapSource; import mobac.program.model.TileImageFormat; import mobac.program.model.TileImageType; +import javax.imageio.ImageIO; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + /** * Creates maps using the Run.GPS Trainer atlas format. - * - * Please note that this atlas format ignores the defined atlas structure. - * *

      - * Run.GPS Atlas format has been designed to support huge collections of maps (2 GB and more) and for very fast access - * (using a numeric index at the beginning of an atlas file). The file format can hold integer values, strings and - * binary data. The file format is described on this page: http://www.rungps.net/wiki/RunGPSAtlasFormat (full sample - * source code is available). + * Please note that this atlas format ignores the defined atlas structure. + * + *

      + * Run.GPS Atlas format has been designed to support huge collections of maps (2 + * GB and more) and for very fast access (using a numeric index at the beginning + * of an atlas file). The file format can hold integer values, strings and + * binary data. The file format is described on this page: + * http://www.rungps.net/wiki/RunGPSAtlasFormat (full sample source code is + * available). *

      */ @AtlasCreatorName(value = "Run.GPS Atlas", type = "RunGPS") @@ -62,8 +63,8 @@ public class RunGPSAtlas extends AtlasCreator { } @Override - public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) throws IOException, InterruptedException, - AtlasTestException { + public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) + throws IOException, InterruptedException, AtlasTestException { super.startAtlasCreation(atlas, customAtlasDir); String atlasName = this.atlas.getName().replace(' ', '_'); atlasIndex = new RunGPSAtlasFile(atlasDir.getPath() + File.separatorChar + atlasName + RunGPSAtlasFile.SUFFIX, @@ -110,9 +111,10 @@ public class RunGPSAtlas extends AtlasCreator { } public void createMap() throws MapCreationException, InterruptedException { - if (mapSource.getTileImageType() != TileImageType.PNG) + if (mapSource.getTileImageType() != TileImageType.PNG) { // If the tile image format is not png we have to convert it mapDlTileProvider = new ConvertedRawTileProvider(mapDlTileProvider, TileImageFormat.PNG); + } createTiles(); } @@ -138,10 +140,12 @@ public class RunGPSAtlas extends AtlasCreator { } protected boolean writeTile(String cache, byte[] tileData, int x, int y, int zoom) throws IOException { - if (zoom < minZoom) + if (zoom < minZoom) { minZoom = zoom; - if (zoom > maxZoom) + } + if (zoom > maxZoom) { maxZoom = zoom; + } String cacheKey = cache + "-" + zoom + "-" + x + "-" + y; diff --git a/src/main/java/mobac/program/atlascreators/SportsTracker.java b/mobac/src/main/java/mobac/program/atlascreators/SportsTracker.java similarity index 87% rename from src/main/java/mobac/program/atlascreators/SportsTracker.java rename to mobac/src/main/java/mobac/program/atlascreators/SportsTracker.java index 783c93b..3de5c90 100644 --- a/src/main/java/mobac/program/atlascreators/SportsTracker.java +++ b/mobac/src/main/java/mobac/program/atlascreators/SportsTracker.java @@ -1,27 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; - -import javax.imageio.ImageIO; - import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; import mobac.program.annotations.AtlasCreatorName; @@ -36,21 +30,35 @@ import mobac.program.model.TileImageParameters; import mobac.program.model.TileImageParameters.Name; import mobac.utilities.Utilities; +import javax.imageio.ImageIO; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; + /** * [Nokia] Sports Tracker - * - * */ @AtlasCreatorName(value = "Sports Tracker", type = "NST") -@SupportedParameters(names = { Name.format }) +@SupportedParameters(names = {Name.format}) public class SportsTracker extends AtlasCreator { + protected static final char[] NUM_CHAR = {'q', 'r', 't', 's'}; protected File mapDir = null; - protected MapTileWriter mapTileWriter = null; - protected String tileType = null; + public static String getTileName(int zoom, int tilex, int tiley) { + char[] tileNum = new char[zoom + 1]; + tileNum[0] = 't'; + for (int i = zoom; i > 0; i--) { + int num = (tilex % 2) | ((tiley % 2) << 1); + tileNum[i] = NUM_CHAR[num]; + tilex >>= 1; + tiley >>= 1; + } + return new String(tileNum); + } + @Override public boolean testMapSource(MapSource mapSource) { return MercatorPower2MapSpace.INSTANCE_256.equals(mapSource.getMapSpace()); @@ -89,8 +97,9 @@ public class SportsTracker extends AtlasCreator { atlasProgress.incMapCreationProgress(); try { byte[] sourceTileData = mapDlTileProvider.getTileData(x, y); - if (sourceTileData != null) + if (sourceTileData != null) { writeTile(x, y, sourceTileData); + } } catch (IOException e) { throw new MapCreationException("Error writing tile image: " + e.getMessage(), map, e); } @@ -102,8 +111,9 @@ public class SportsTracker extends AtlasCreator { String tileName = getTileName(zoom, tilex, tiley); int count = tileName.length(); int dirCount = count / 3; - if ((count % 3 == 0) & (dirCount > 0)) + if ((count % 3 == 0) & (dirCount > 0)) { dirCount--; + } File tileDir = mapDir; for (int i = 0; i < dirCount; i++) { int start = i * 3; @@ -111,7 +121,8 @@ public class SportsTracker extends AtlasCreator { tileDir = new File(tileDir, dirName); } // File extension needs to be jpg (requested by telemaxx) - // see https://sourceforge.net/tracker/?func=detail&atid=1105497&aid=3066161&group_id=238075 + // see + // https://sourceforge.net/tracker/?func=detail&atid=1105497&aid=3066161&group_id=238075 String fileName = tileName + ".jpg"; File file = new File(tileDir, fileName); writeTile(file, tileData); @@ -119,26 +130,9 @@ public class SportsTracker extends AtlasCreator { protected void writeTile(File file, byte[] tileData) throws IOException { Utilities.mkDirs(file.getParentFile()); - FileOutputStream out = new FileOutputStream(file); - try { + try (FileOutputStream out = new FileOutputStream(file)) { out.write(tileData); - } finally { - Utilities.closeStream(out); } } - protected static final char[] NUM_CHAR = { 'q', 'r', 't', 's' }; - - public static String getTileName(int zoom, int tilex, int tiley) { - char[] tileNum = new char[zoom + 1]; - tileNum[0] = 't'; - for (int i = zoom; i > 0; i--) { - int num = (tilex % 2) | ((tiley % 2) << 1); - tileNum[i] = NUM_CHAR[num]; - tilex >>= 1; - tiley >>= 1; - } - return new String(tileNum); - } - } diff --git a/src/main/java/mobac/program/atlascreators/TTQV.java b/mobac/src/main/java/mobac/program/atlascreators/TTQV.java similarity index 91% rename from src/main/java/mobac/program/atlascreators/TTQV.java rename to mobac/src/main/java/mobac/program/atlascreators/TTQV.java index 118989e..87bdb31 100644 --- a/src/main/java/mobac/program/atlascreators/TTQV.java +++ b/mobac/src/main/java/mobac/program/atlascreators/TTQV.java @@ -1,29 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.util.Locale; - import mobac.exceptions.MapCreationException; import mobac.program.ProgramInfo; import mobac.program.annotations.AtlasCreatorName; @@ -32,6 +24,14 @@ import mobac.program.interfaces.MapInterface; import mobac.program.interfaces.MapSpace; import mobac.utilities.Utilities; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.Locale; + /** * Touratech QV */ @@ -55,11 +55,8 @@ public class TTQV extends Ozi { } private void writeCalFile() throws MapCreationException { - FileOutputStream fout = null; - try { - fout = new FileOutputStream(new File(layerDir, mapName + "_png.cal")); - OutputStreamWriter mapWriter = new OutputStreamWriter(fout, TEXT_FILE_CHARSET); - + File calFile = new File(layerDir, mapName + "_png.cal"); + try (OutputStreamWriter mapWriter = new OutputStreamWriter(new FileOutputStream(calFile), TEXT_FILE_CHARSET)) { MapSpace mapSpace = mapSource.getMapSpace(); double longitudeMin = mapSpace.cXToLon(xMin * tileSize, zoom); @@ -115,11 +112,8 @@ public class TTQV extends Ozi { mapWriter.write(String.format(Locale.ENGLISH, cLine, 4, "lon", longitudeMin)); mapWriter.flush(); - mapWriter.close(); } catch (IOException e) { throw new MapCreationException("Error writing cal file: " + e.getMessage(), map, e); - } finally { - Utilities.closeStream(fout); } } } diff --git a/src/main/java/mobac/program/atlascreators/TileStoreDownload.java b/mobac/src/main/java/mobac/program/atlascreators/TileStoreDownload.java similarity index 91% rename from src/main/java/mobac/program/atlascreators/TileStoreDownload.java rename to mobac/src/main/java/mobac/program/atlascreators/TileStoreDownload.java index 522ec88..6b3c741 100644 --- a/src/main/java/mobac/program/atlascreators/TileStoreDownload.java +++ b/mobac/src/main/java/mobac/program/atlascreators/TileStoreDownload.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; diff --git a/src/main/java/mobac/program/atlascreators/TomTomRaster.java b/mobac/src/main/java/mobac/program/atlascreators/TomTomRaster.java similarity index 86% rename from src/main/java/mobac/program/atlascreators/TomTomRaster.java rename to mobac/src/main/java/mobac/program/atlascreators/TomTomRaster.java index b81b2a2..94e5f14 100644 --- a/src/main/java/mobac/program/atlascreators/TomTomRaster.java +++ b/mobac/src/main/java/mobac/program/atlascreators/TomTomRaster.java @@ -1,37 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.StringWriter; -import java.text.NumberFormat; - -import javax.imageio.ImageIO; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; @@ -43,14 +27,28 @@ import mobac.program.interfaces.MapSpace; import mobac.program.interfaces.MapSpace.ProjectionCategory; import mobac.program.interfaces.TileImageDataWriter; import mobac.program.tiledatawriter.TileImageJpegDataWriter; -import mobac.utilities.Charsets; import mobac.utilities.Utilities; +import javax.imageio.ImageIO; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.text.NumberFormat; + /** - * * http://sourceforge.net/p/mobac/feature-requests/225/ * http://create.tomtom.com/manuals/create-your-own-content/index.html?map_overlays.htm - * + * * @author r_x */ @AtlasCreatorName(value = "TomTom Raster (image + SAT)") @@ -61,8 +59,8 @@ public class TomTomRaster extends AtlasCreator { @Override public boolean testMapSource(MapSource mapSource) { MapSpace mapSpace = mapSource.getMapSpace(); - return (mapSpace instanceof MercatorPower2MapSpace && ProjectionCategory.SPHERE.equals(mapSpace - .getProjectionCategory())); + return (mapSpace instanceof MercatorPower2MapSpace + && ProjectionCategory.SPHERE.equals(mapSpace.getProjectionCategory())); } @Override @@ -75,9 +73,10 @@ public class TomTomRaster extends AtlasCreator { for (MapInterface map : layer) { int w = map.getMaxTileCoordinate().x - map.getMinTileCoordinate().x; int h = map.getMaxTileCoordinate().y - map.getMinTileCoordinate().y; - if (w > maxMapSize || h > maxMapSize) - throw new AtlasTestException("Map size too large for memory (is: " + Math.max(w, h) + " max: " - + maxMapSize + ")", map); + if (w > maxMapSize || h > maxMapSize) { + throw new AtlasTestException( + "Map size too large for memory (is: " + Math.max(w, h) + " max: " + maxMapSize + ")", map); + } } } @@ -106,7 +105,6 @@ public class TomTomRaster extends AtlasCreator { protected void createImage() throws InterruptedException, MapCreationException { atlasProgress.initMapCreation((xMax - xMin + 1) * (yMax - yMin + 1)); - ImageIO.setUseCache(false); int mapWidth = (xMax - xMin + 1) * tileSize; int mapHeight = (yMax - yMin + 1) * tileSize; @@ -122,25 +120,29 @@ public class TomTomRaster extends AtlasCreator { scaleFactor = (double) getMaxImageSize() / (double) len; if (mapWidth != mapHeight) { // Map is not rectangle -> adapt height or width - if (mapWidth > mapHeight) + if (mapWidth > mapHeight) { imageHeight = (int) (scaleFactor * mapHeight); - else + } else { imageWidth = (int) (scaleFactor * mapWidth); + } } } - if (imageHeight < 0 || imageWidth < 0) + if (imageHeight < 0 || imageWidth < 0) { throw new MapCreationException("Invalid map size: (width/height: " + imageWidth + "/" + imageHeight + ")", map); + } long imageSize = 3l * ((long) imageWidth) * ((long) imageHeight); - if (imageSize > Integer.MAX_VALUE) + if (imageSize > Integer.MAX_VALUE) { throw new MapCreationException("Map image too large: (width/height: " + imageWidth + "/" + imageHeight + ") - reduce the map size and try again", map); + } BufferedImage tileImage = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_3BYTE_BGR); Graphics2D graphics = tileImage.createGraphics(); try { if (scaleImage) { graphics.setTransform(AffineTransform.getScaleInstance(scaleFactor, scaleFactor)); - graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BILINEAR); } int lineY = 0; for (int y = yMin; y <= yMax; y++) { @@ -170,10 +172,10 @@ public class TomTomRaster extends AtlasCreator { protected void writeTileImage(BufferedImage tileImage) throws MapCreationException { TileImageDataWriter writer; if (parameters != null) { - writer = parameters.getFormat().getDataWriter(); - } else + writer = parameters.getFormat().getDataWriterBuilder().build(); + } else { writer = new TileImageJpegDataWriter(0.9); - writer.initialize(); + } try { int initialBufferSize = tileImage.getWidth() * tileImage.getHeight() / 4; ByteArrayOutputStream buf = new ByteArrayOutputStream(initialBufferSize); @@ -190,12 +192,14 @@ public class TomTomRaster extends AtlasCreator { writeSatFile(imageFileName, tileImage.getWidth(), tileImage.getHeight()); } catch (Exception e) { throw new MapCreationException(map, e); + } finally { + writer.close(); } } /** * SAT file content - * + * *
       	 * Line 1 - filename of the image file.
       	 * Line 2 - GPS coordinate of the top left corner of the image (longitude).
      @@ -228,13 +232,13 @@ public class TomTomRaster extends AtlasCreator {
       		sw.write(latitudeMin + "\r\n");
       		sw.write("0\r\n");
       		sw.write("65535\r\n");
      -		sw.write(Integer.toString(width) + "\r\n");
      +		sw.write(width + "\r\n");
       		sw.write(Integer.toString(height));
       
       		int i = imageFileName.lastIndexOf('.');
       		String satFileName = imageFileName.substring(0, i) + ".sat";
      -		FileOutputStream fout = new FileOutputStream(new File(layerDir,satFileName));
      -		OutputStreamWriter writer = new OutputStreamWriter(fout, Charsets.ISO_8859_1);
      +		FileOutputStream fout = new FileOutputStream(new File(layerDir, satFileName));
      +		OutputStreamWriter writer = new OutputStreamWriter(fout, StandardCharsets.ISO_8859_1);
       		writer.append(sw.toString());
       		writer.flush();
       		writer.close();
      diff --git a/src/main/java/mobac/program/atlascreators/TrekBuddy.java b/mobac/src/main/java/mobac/program/atlascreators/TrekBuddy.java
      similarity index 85%
      rename from src/main/java/mobac/program/atlascreators/TrekBuddy.java
      rename to mobac/src/main/java/mobac/program/atlascreators/TrekBuddy.java
      index a5f625d..21a9fef 100644
      --- a/src/main/java/mobac/program/atlascreators/TrekBuddy.java
      +++ b/mobac/src/main/java/mobac/program/atlascreators/TrekBuddy.java
      @@ -1,33 +1,21 @@
       /*******************************************************************************
        * Copyright (c) MOBAC developers
      - * 
      + *
        * This program is free software: you can redistribute it and/or modify
        * it under the terms of the GNU General Public License as published by
        * the Free Software Foundation, either version 2 of the License, or
        * (at your option) any later version.
      - * 
      + *
        * This program is distributed in the hope that it will be useful,
        * but WITHOUT ANY WARRANTY; without even the implied warranty of
        * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        * GNU General Public License for more details.
      - * 
      + *
        * You should have received a copy of the GNU General Public License
      - * along with this program.  If not, see .
      + * along with this program.  If not, see .
        ******************************************************************************/
       package mobac.program.atlascreators;
       
      -import java.io.BufferedWriter;
      -import java.io.File;
      -import java.io.FileOutputStream;
      -import java.io.FileWriter;
      -import java.io.IOException;
      -import java.io.OutputStream;
      -import java.io.OutputStreamWriter;
      -import java.io.Writer;
      -import java.util.Locale;
      -
      -import javax.imageio.ImageIO;
      -
       import mobac.exceptions.AtlasTestException;
       import mobac.exceptions.MapCreationException;
       import mobac.mapsources.mapspace.MercatorPower2MapSpace;
      @@ -47,8 +35,19 @@ import mobac.program.model.TileImageParameters.Name;
       import mobac.utilities.Utilities;
       import mobac.utilities.geo.GeoUtils;
       
      +import javax.imageio.ImageIO;
      +import java.io.BufferedWriter;
      +import java.io.File;
      +import java.io.FileOutputStream;
      +import java.io.FileWriter;
      +import java.io.IOException;
      +import java.io.OutputStream;
      +import java.io.OutputStreamWriter;
      +import java.io.Writer;
      +import java.util.Locale;
      +
       @AtlasCreatorName(value = "TrekBuddy untared atlas", type = "UntaredAtlas")
      -@SupportedParameters(names = { Name.format, Name.height, Name.width })
      +@SupportedParameters(names = {Name.format, Name.height, Name.width})
       public class TrekBuddy extends AtlasCreator {
       
       	protected static final String FILENAME_PATTERN = "t_%d_%d.%s";
      @@ -60,13 +59,13 @@ public class TrekBuddy extends AtlasCreator {
       	@Override
       	public boolean testMapSource(MapSource mapSource) {
       		MapSpace mapSpace = mapSource.getMapSpace();
      -		return (mapSpace instanceof MercatorPower2MapSpace && ProjectionCategory.SPHERE.equals(mapSpace
      -				.getProjectionCategory()));
      +		return (mapSpace instanceof MercatorPower2MapSpace
      +				&& ProjectionCategory.SPHERE.equals(mapSpace.getProjectionCategory()));
       		// TODO supports Mercator ellipsoid?
       	}
       
      -	public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir) throws IOException, InterruptedException,
      -			AtlasTestException {
      +	public void startAtlasCreation(AtlasInterface atlas, File customAtlasDir)
      +			throws IOException, InterruptedException, AtlasTestException {
       		super.startAtlasCreation(atlas, customAtlasDir);
       	}
       
      @@ -84,12 +83,8 @@ public class TrekBuddy extends AtlasCreator {
       
       	protected void writeMapFile() throws IOException {
       		File mapFile = new File(mapDir, map.getName() + ".map");
      -		FileOutputStream mapFileStream = null;
      -		try {
      -			mapFileStream = new FileOutputStream(mapFile);
      +		try (FileOutputStream mapFileStream = new FileOutputStream(mapFile)) {
       			writeMapFile(mapFileStream);
      -		} finally {
      -			Utilities.closeStream(mapFileStream);
       		}
       	}
       
      @@ -111,8 +106,8 @@ public class TrekBuddy extends AtlasCreator {
       		int width = (xMax - xMin + 1) * tileSize;
       		int height = (yMax - yMin + 1) * tileSize;
       
      -		mapWriter.write(prepareMapString(imageFileName, longitudeMin, longitudeMax, latitudeMin, latitudeMax, width,
      -				height));
      +		mapWriter.write(
      +				prepareMapString(imageFileName, longitudeMin, longitudeMax, latitudeMin, latitudeMax, width, height));
       		mapWriter.flush();
       	}
       
      @@ -128,10 +123,11 @@ public class TrekBuddy extends AtlasCreator {
       
       			// Select the tile creator instance based on whether tile image
       			// parameters has been set or not
      -			if (parameters != null)
      +			if (parameters != null) {
       				createCustomTiles();
      -			else
      +			} else {
       				createTiles();
      +			}
       
       			mapTileWriter.finalizeMap();
       		} catch (MapCreationException e) {
      @@ -149,25 +145,23 @@ public class TrekBuddy extends AtlasCreator {
       
       	/**
       	 * New experimental custom tile size algorithm implementation.
      -	 * 
      -	 * It creates each custom sized tile separately. Therefore each original tile (256x256) will be loaded and painted
      -	 * multiple times. Therefore this implementation needs much more CPU power as each original tile is loaded at least
      -	 * once and each generated tile has to be saved.
      -	 * 
      +	 * 

      + * It creates each custom sized tile separately. Therefore each original tile + * (256x256) will be loaded and painted multiple times. Therefore this + * implementation needs much more CPU power as each original tile is loaded at + * least once and each generated tile has to be saved. + * * @throws MapCreationException */ protected void createCustomTiles() throws InterruptedException, MapCreationException { log.debug("Starting map creation using custom parameters: " + parameters); - CacheTileProvider ctp = new CacheTileProvider(mapDlTileProvider); - try { + try (CacheTileProvider ctp = new CacheTileProvider(mapDlTileProvider)) { mapDlTileProvider = ctp; MapTileBuilder mapTileBuilder = new MapTileBuilder(this, mapTileWriter, true); atlasProgress.initMapCreation(mapTileBuilder.getCustomTileCount()); mapTileBuilder.createTiles(); - } finally { - ctp.cleanup(); } } @@ -190,8 +184,7 @@ public class TrekBuddy extends AtlasCreator { if (sourceTileData != null) { mapTileWriter.writeTile(tilex, tiley, tileType, sourceTileData); } else { - log.trace(String.format("Tile x=%d y=%d not found in tile archive - creating default", tilex, - tiley)); + log.trace("Tile x={} y={} not found in tile archive - creating default", tilex, tiley); mapTileWriter.writeTile(tilex, tiley, tileType, emptyTileData); } } catch (IOException e) { @@ -203,56 +196,6 @@ public class TrekBuddy extends AtlasCreator { } } - private class FileTileWriter implements MapTileWriter { - - File setFolder; - Writer setFileWriter; - - int tileHeight = 256; - int tileWidth = 256; - - public FileTileWriter() throws IOException { - super(); - setFolder = new File(mapDir, "set"); - Utilities.mkDir(setFolder); - log.debug("Writing tiles to set folder: " + setFolder); - File setFile = new File(mapDir, map.getName() + ".set"); - if (parameters != null) { - tileHeight = parameters.getHeight(); - tileWidth = parameters.getWidth(); - } - try { - setFileWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(setFile), - TEXT_FILE_CHARSET)); - } catch (IOException e) { - log.error("", e); - } - } - - public void writeTile(int tilex, int tiley, String imageFormat, byte[] tileData) throws IOException { - String tileFileName = String.format(FILENAME_PATTERN, (tilex * tileWidth), (tiley * tileHeight), - imageFormat); - - File f = new File(setFolder, tileFileName); - FileOutputStream out = new FileOutputStream(f); - setFileWriter.write(tileFileName + "\r\n"); - try { - out.write(tileData); - } finally { - Utilities.closeStream(out); - } - } - - public void finalizeMap() { - try { - setFileWriter.flush(); - } catch (IOException e) { - log.error("", e); - } - Utilities.closeWriter(setFileWriter); - } - } - protected String prepareMapString(String fileName, double longitudeMin, double longitudeMax, double latitudeMin, double latitudeMax, int width, int height) { @@ -322,13 +265,58 @@ public class TrekBuddy extends AtlasCreator { public void createAtlasTbaFile(String name) { File crtba = new File(atlasDir.getAbsolutePath(), name + ".tba"); - try { - FileWriter fw = new FileWriter(crtba); + try (FileWriter fw = new FileWriter(crtba)) { fw.write("Atlas 1.0\r\n"); - fw.close(); } catch (IOException e) { log.error("", e); } } + private class FileTileWriter implements MapTileWriter { + + File setFolder; + Writer setFileWriter; + + int tileHeight = 256; + int tileWidth = 256; + + public FileTileWriter() throws IOException { + super(); + setFolder = new File(mapDir, "set"); + Utilities.mkDir(setFolder); + log.debug("Writing tiles to set folder: " + setFolder); + File setFile = new File(mapDir, map.getName() + ".set"); + if (parameters != null) { + tileHeight = parameters.getHeight(); + tileWidth = parameters.getWidth(); + } + try { + setFileWriter = new BufferedWriter( + new OutputStreamWriter(new FileOutputStream(setFile), TEXT_FILE_CHARSET)); + } catch (IOException e) { + log.error("", e); + } + } + + public void writeTile(int tilex, int tiley, String imageFormat, byte[] tileData) throws IOException { + String tileFileName = String.format(FILENAME_PATTERN, (tilex * tileWidth), (tiley * tileHeight), + imageFormat); + + File f = new File(setFolder, tileFileName); + setFileWriter.write(tileFileName + "\r\n"); + try (FileOutputStream out = new FileOutputStream(f)) { + out.write(tileData); + } + } + + public void finalizeMap() { + try { + setFileWriter.flush(); + } catch (IOException e) { + log.error("", e); + } + Utilities.closeQuietly(setFileWriter); + } + } + } diff --git a/src/main/java/mobac/program/atlascreators/TrekBuddyTared.java b/mobac/src/main/java/mobac/program/atlascreators/TrekBuddyTared.java similarity index 72% rename from src/main/java/mobac/program/atlascreators/TrekBuddyTared.java rename to mobac/src/main/java/mobac/program/atlascreators/TrekBuddyTared.java index 1ecb1f4..be35948 100644 --- a/src/main/java/mobac/program/atlascreators/TrekBuddyTared.java +++ b/mobac/src/main/java/mobac/program/atlascreators/TrekBuddyTared.java @@ -1,73 +1,82 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; +import mobac.exceptions.AtlasTestException; +import mobac.program.annotations.AtlasCreatorName; +import mobac.program.atlascreators.impl.MapTileWriter; +import mobac.program.interfaces.LayerInterface; +import mobac.program.interfaces.MapInterface; +import mobac.utilities.Utilities; +import mobac.utilities.tar.TarArchive; +import mobac.utilities.tar.TarTmiArchive; +import org.apache.commons.io.IOUtils; + import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.LinkedList; import java.util.List; -import org.apache.commons.io.FileUtils; - -import mobac.program.annotations.AtlasCreatorName; -import mobac.program.atlascreators.impl.MapTileWriter; -import mobac.utilities.Utilities; -import mobac.utilities.tar.TarArchive; -import mobac.utilities.tar.TarTmiArchive; - @AtlasCreatorName(value = "TrekBuddy tared atlas", type = "TaredAtlas") public class TrekBuddyTared extends TrekBuddy { + @Override + protected void testAtlas() throws AtlasTestException { + super.testAtlas(); + for (LayerInterface layer : atlas) { + for (MapInterface map : layer) { + String mapFileName = layer.getName() + "/" + map.getName() + "/" + map.getName() + ".map"; + if (mapFileName.length() > 100) { + throw new AtlasTestException("Layer and map name too long for Trekbuddy Tar format!\n" + mapFileName + + "\n\nCurrent length: " + mapFileName.length() + + " characters\nMaximum length: 100 characters", map); + } + } + } + } + @Override public void finishAtlasCreation() { createAtlasTarArchive("cr"); } private void createAtlasTarArchive(String name) { - log.trace("Creating cr.tar for atlas in dir \"" + atlasDir.getPath() + "\""); + log.trace("Creating cr.tar for atlas in dir \"{}\"", atlasDir.getPath()); File[] atlasLayerDirs = Utilities.listSubDirectories(atlasDir); - List atlasMapDirs = new LinkedList(); - for (File dir : atlasLayerDirs) + List atlasMapDirs = new LinkedList<>(); + for (File dir : atlasLayerDirs) { Utilities.addSubDirectories(atlasMapDirs, dir, 0); + } - TarArchive ta = null; File crFile = new File(atlasDir, name + ".tar"); - try { - ta = new TarArchive(crFile, atlasDir); - + try (TarArchive ta = new TarArchive(crFile, atlasDir)) { ta.writeFileFromData(name + ".tba", "Atlas 1.0\r\n".getBytes()); for (File mapDir : atlasMapDirs) { ta.writeFile(mapDir); File mapFile = new File(mapDir, mapDir.getName() + ".map"); ta.writeFile(mapFile); - try { - mapFile.delete(); - } catch (Exception e) { - } + mapFile.delete(); } ta.writeEndofArchive(); } catch (IOException e) { log.error("Failed writing tar file \"" + crFile.getPath() + "\"", e); - } finally { - if (ta != null) - ta.close(); } } @@ -112,8 +121,9 @@ public class TrekBuddyTared extends TrekBuddy { ta.writeEndofArchive(); } catch (IOException e) { log.error("", e); + } finally { + IOUtils.closeQuietly(ta); } - ta.close(); } } diff --git a/src/main/java/mobac/program/atlascreators/TwoNavRMAP.java b/mobac/src/main/java/mobac/program/atlascreators/TwoNavRMAP.java similarity index 87% rename from src/main/java/mobac/program/atlascreators/TwoNavRMAP.java rename to mobac/src/main/java/mobac/program/atlascreators/TwoNavRMAP.java index 437d9f8..600f97e 100644 --- a/src/main/java/mobac/program/atlascreators/TwoNavRMAP.java +++ b/mobac/src/main/java/mobac/program/atlascreators/TwoNavRMAP.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ /* * add to mobac.program.model.AtlasOutputFormat.java @@ -23,22 +23,6 @@ */ package mobac.program.atlascreators; -import java.awt.Graphics2D; -import java.awt.geom.AffineTransform; -import java.awt.image.AffineTransformOp; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.util.Locale; - -import javax.imageio.ImageIO; - import mobac.exceptions.AtlasTestException; import mobac.exceptions.MapCreationException; import mobac.mapsources.mapspace.MercatorPower2MapSpace; @@ -57,254 +41,35 @@ import mobac.program.model.TileImageType; import mobac.program.tiledatawriter.TileImageJpegDataWriter; import mobac.utilities.Utilities; -import org.apache.log4j.Level; +import javax.imageio.ImageIO; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.Locale; /** - * * Creates one RMAP file per layer. - * + * * @author Luka Logar * @author r_x - * */ @AtlasCreatorName(value = "TwoNav (RMAP)") -@SupportedParameters(names = { Name.format }) +@SupportedParameters(names = {Name.format}) public class TwoNavRMAP extends AtlasCreator { private RmapFile rmapFile = null; - private class ZoomLevel { - - private int index = 0; - private long offset = 0; - private int width = 0; - private int height = 0; - private int xTiles = 0; - private int yTiles = 0; - private long jpegOffsets[][] = null; - private int zoom = 0; - private boolean dl = false; - - private void writeHeader() throws IOException { - if (offset == 0) { - offset = rmapFile.getFilePointer(); - } else { - rmapFile.seek(offset); - } - log.trace(String.format("Writing ZoomLevel %d (%dx%d pixels, %dx%d tiles) header at offset %d", index, - width, height, xTiles, yTiles, offset)); - rmapFile.writeIntI(width); - rmapFile.writeIntI(-height); - rmapFile.writeIntI(xTiles); - rmapFile.writeIntI(yTiles); - if (jpegOffsets == null) { - jpegOffsets = new long[xTiles][yTiles]; - } - for (int y = 0; y < yTiles; y++) { - for (int x = 0; x < xTiles; x++) { - rmapFile.writeLongI(jpegOffsets[x][y]); - } - } - } - - private BufferedImage loadJpegAtOffset(long offset) throws IOException { - if (offset == 0) { - throw new IOException("offset == 0"); - } - rmapFile.seek(offset); - int TagId = rmapFile.readIntI(); - if (TagId != 7) { - throw new IOException("TagId != 7"); - } - int TagLen = rmapFile.readIntI(); - byte[] jpegImageBuf = new byte[TagLen]; - rmapFile.readFully(jpegImageBuf); - ByteArrayInputStream input = new ByteArrayInputStream(jpegImageBuf); - return ImageIO.read(input); - } - - private byte[] getTileData(TileImageDataWriter writer, ZoomLevel source, int x, int y) throws IOException { - log.trace(String.format("Shrinking jpegs (%d,%d,%d - %d,%d,%d)", source.index, x, y, source.index, - (x + 1 < source.xTiles) ? x + 1 : x, (y + 1 < source.yTiles) ? y + 1 : y)); - BufferedImage bi11 = loadJpegAtOffset(source.jpegOffsets[x][y]); - BufferedImage bi21 = (x + 1 < source.xTiles) ? loadJpegAtOffset(source.jpegOffsets[x + 1][y]) : null; - BufferedImage bi12 = (y + 1 < source.yTiles) ? loadJpegAtOffset(source.jpegOffsets[x][y + 1]) : null; - BufferedImage bi22 = (x + 1 < source.xTiles) && (y + 1 < source.yTiles) ? loadJpegAtOffset(source.jpegOffsets[x + 1][y + 1]) - : null; - int biWidth = bi11.getWidth() + (bi21 != null ? bi21.getWidth() : 0); - int biHeight = bi11.getHeight() + (bi12 != null ? bi12.getHeight() : 0); - BufferedImage bi = new BufferedImage(biWidth, biHeight, BufferedImage.TYPE_3BYTE_BGR); - Graphics2D g = bi.createGraphics(); - g.drawImage(bi11, 0, 0, null); - if (bi21 != null) { - g.drawImage(bi21, bi11.getWidth(), 0, null); - } - if (bi12 != null) { - g.drawImage(bi12, 0, bi11.getHeight(), null); - } - if (bi22 != null) { - g.drawImage(bi22, bi11.getWidth(), bi11.getHeight(), null); - } - AffineTransformOp op = new AffineTransformOp(new AffineTransform(0.5, 0, 0, 0.5, 0, 0), - AffineTransformOp.TYPE_BILINEAR); - BufferedImage biOut = new BufferedImage(biWidth / 2, biHeight / 2, BufferedImage.TYPE_3BYTE_BGR); - op.filter(bi, biOut); - ByteArrayOutputStream buffer = new ByteArrayOutputStream(biOut.getWidth() * biOut.getHeight() * 4); - writer.processImage(biOut, buffer); - g.dispose(); - return buffer.toByteArray(); - } - - private void shrinkFrom(ZoomLevel source) { - try { - TileImageDataWriter writer = new TileImageJpegDataWriter(0.9); - writer.initialize(); - writeHeader(); - atlasProgress.initMapCreation(xTiles * yTiles); - for (int x = 0; x < xTiles; x++) { - for (int y = 0; y < yTiles; y++) { - checkUserAbort(); - atlasProgress.incMapCreationProgress(); - jpegOffsets[x][y] = rmapFile.getFilePointer(); - byte[] tileData = getTileData(writer, source, 2 * x, 2 * y); - rmapFile.seek(jpegOffsets[x][y]); - log.trace(String.format("Writing shrunken jpeg (%d,%d,%d) at offset %d", index, x, y, - jpegOffsets[x][y])); - rmapFile.writeIntI(7); - rmapFile.writeIntI(tileData.length); - rmapFile.write(tileData); - tileData = null; - } - } - } catch (Exception e) { - log.error("Failed generating ZoomLevel " + index + ": " + e.getMessage()); - } - } - } - - private class RmapFile extends RandomAccessFile { - - private String name = ""; - private int width = 0; - private int height = 0; - private int tileWidth = 0; - private int tileHeight = 0; - private double longitudeMin = 0; - private double longitudeMax = 0; - private double latitudeMin = 0; - private double latitudeMax = 0; - private long mapDataOffset = 0; - private ZoomLevel zoomLevels[] = null; - - private RmapFile(File file) throws FileNotFoundException { - super(file, "rw"); - this.name = file.getName(); - } - - private int readIntI() throws IOException { - int ch1 = this.read(); - int ch2 = this.read(); - int ch3 = this.read(); - int ch4 = this.read(); - if ((ch1 | ch2 | ch3 | ch4) < 0) { - throw new IOException(); - } - return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0)); - } - - private void writeIntI(int i) throws IOException { - write((i >>> 0) & 0xFF); - write((i >>> 8) & 0xFF); - write((i >>> 16) & 0xFF); - write((i >>> 24) & 0xFF); - } - - private void writeLongI(long l) throws IOException { - write((int) (l >>> 0) & 0xFF); - write((int) (l >>> 8) & 0xFF); - write((int) (l >>> 16) & 0xFF); - write((int) (l >>> 24) & 0xFF); - write((int) (l >>> 32) & 0xFF); - write((int) (l >>> 40) & 0xFF); - write((int) (l >>> 48) & 0xFF); - write((int) (l >>> 56) & 0xFF); - } - - private void writeHeader() throws IOException { - log.trace("Writing rmap header"); - if (zoomLevels == null) { - throw new IOException("zoomLevels == null"); - } - seek(0); - write("CompeGPSRasterImage".getBytes()); - writeIntI(10); - writeIntI(7); - writeIntI(0); - writeIntI(width); - writeIntI(-height); - writeIntI(24); - writeIntI(1); - writeIntI(tileWidth); - writeIntI(tileHeight); - writeLongI(mapDataOffset); - writeIntI(0); - writeIntI(zoomLevels.length); - for (int n = 0; n < zoomLevels.length; n++) { - writeLongI(zoomLevels[n].offset); - } - } - - private void writeMapInfo() throws IOException { - if (mapDataOffset == 0) { - mapDataOffset = getFilePointer(); - } else { - seek(mapDataOffset); - } - log.trace("Writing MAP data at offset %d" + mapDataOffset); - StringBuffer sbMap = new StringBuffer(); - sbMap.append("CompeGPS MAP File\r\n"); - sbMap.append("

      \r\n"); - sbMap.append("Version=2\r\n"); - sbMap.append("VerCompeGPS=MOBAC\r\n"); - sbMap.append("Projection=2,Mercator,\r\n"); - sbMap.append("Coordinates=1\r\n"); - sbMap.append("Datum=WGS 84\r\n"); - sbMap.append("
      \r\n"); - sbMap.append("\r\n"); - sbMap.append("Bitmap=" + name + "\r\n"); - sbMap.append("BitsPerPixel=0\r\n"); - sbMap.append(String.format("BitmapWidth=%d\r\n", width)); - sbMap.append(String.format("BitmapHeight=%d\r\n", height)); - sbMap.append("Type=10\r\n"); - sbMap.append("\r\n"); - sbMap.append("\r\n"); - String pointLine = "P%d=%d,%d,A,%s,%s\r\n"; - DecimalFormat df = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US); - df.applyPattern("#0.00000000"); - sbMap.append(String.format(pointLine, 0, 0, 0, df.format(longitudeMin), df.format(latitudeMax))); - sbMap.append(String.format(pointLine, 1, width - 1, 0, df.format(longitudeMax), df.format(latitudeMax))); - sbMap.append(String.format(pointLine, 2, width - 1, height - 1, df.format(longitudeMax), - df.format(latitudeMin))); - sbMap.append(String.format(pointLine, 3, 0, height - 1, df.format(longitudeMin), df.format(latitudeMin))); - sbMap.append("\r\n"); - sbMap.append("\r\n"); - String polyLine = "M%d=%d,%d\r\n"; - sbMap.append(String.format(polyLine, 0, 0, 0)); - sbMap.append(String.format(polyLine, 1, width, 0)); - sbMap.append(String.format(polyLine, 2, width, height)); - sbMap.append(String.format(polyLine, 3, 0, height)); - sbMap.append("\r\n"); - writeIntI(1); - writeIntI(sbMap.length()); - write(sbMap.toString().getBytes()); - } - } - - // ************************************************************ - public TwoNavRMAP() { super(); - log.setLevel(Level.TRACE); } @Override @@ -331,27 +96,31 @@ public class TwoNavRMAP extends AtlasCreator { } for (int m = 0; m < layer.getMapCount(); m++) { if ((mapN.getZoom() == layer.getMap(m).getZoom()) && (m != n)) { - throw new AtlasTestException("Several maps with the same zoom level within the same layer " - + "are not supported!"); + throw new AtlasTestException( + "Several maps with the same zoom level within the same layer " + "are not supported!"); } } } } } + // ************************************************************ + public boolean testMapSource(MapSource mapSource) { MapSpace mapSpace = mapSource.getMapSpace(); - return (mapSpace instanceof MercatorPower2MapSpace && ProjectionCategory.SPHERE.equals(mapSpace - .getProjectionCategory())); + return (mapSpace instanceof MercatorPower2MapSpace + && ProjectionCategory.SPHERE.equals(mapSpace.getProjectionCategory())); } @Override public void initLayerCreation(LayerInterface layer) throws IOException { - if (rmapFile != null) + if (rmapFile != null) { throw new RuntimeException("Layer mismatch - last layer has not been finished correctly!"); + } super.initLayerCreation(layer); - // Logging.configureConsoleLogging(org.apache.log4j.Level.ALL, new SimpleLayout()); + // Logging.configureConsoleLogging(org.apache.log4j.Level.ALL, new + // SimpleLayout()); rmapFile = new RmapFile(new File(atlasDir, layer.getName() + ".rmap")); @@ -369,14 +138,14 @@ public class TwoNavRMAP extends AtlasCreator { } } - log.trace("rmap width = " + rmapFile.width); - log.trace("rmap height = " + rmapFile.height); + log.trace("rmap width = {}", rmapFile.width); + log.trace("rmap height = {}", rmapFile.height); rmapFile.tileWidth = layer.getMap(DefaultMap).getTileSize().width; rmapFile.tileHeight = layer.getMap(DefaultMap).getTileSize().height; - log.trace("rmap tileWidth = " + rmapFile.tileWidth); - log.trace("rmap tileHeight = " + rmapFile.tileHeight); + log.trace("rmap tileWidth = {}", rmapFile.tileWidth); + log.trace("rmap tileHeight = {}", rmapFile.tileHeight); MapSpace mapSpace = layer.getMap(DefaultMap).getMapSource().getMapSpace(); rmapFile.longitudeMin = mapSpace.cXToLon(layer.getMap(DefaultMap).getMinTileCoordinate().x, @@ -412,10 +181,10 @@ public class TwoNavRMAP extends AtlasCreator { rmapFile.zoomLevels[n].index = n; rmapFile.zoomLevels[n].width = (int) Math.round(width); rmapFile.zoomLevels[n].height = (int) Math.round(height); - rmapFile.zoomLevels[n].xTiles = (int) Math.ceil((double) rmapFile.zoomLevels[n].width - / (double) rmapFile.tileWidth); - rmapFile.zoomLevels[n].yTiles = (int) Math.ceil((double) rmapFile.zoomLevels[n].height - / (double) rmapFile.tileHeight); + rmapFile.zoomLevels[n].xTiles = (int) Math + .ceil((double) rmapFile.zoomLevels[n].width / (double) rmapFile.tileWidth); + rmapFile.zoomLevels[n].yTiles = (int) Math + .ceil((double) rmapFile.zoomLevels[n].height / (double) rmapFile.tileHeight); rmapFile.zoomLevels[n].jpegOffsets = new long[rmapFile.zoomLevels[n].xTiles][rmapFile.zoomLevels[n].yTiles]; rmapFile.zoomLevels[n].zoom = layer.getMap(DefaultMap).getZoom() - n; rmapFile.zoomLevels[n].dl = false; @@ -429,9 +198,9 @@ public class TwoNavRMAP extends AtlasCreator { } for (int n = 0; n < rmapFile.zoomLevels.length; n++) { - log.trace(String.format("zoomLevels[%d] zoom=%d %dx%d pixels, %dx%d tiles %s", - rmapFile.zoomLevels[n].index, rmapFile.zoomLevels[n].zoom, rmapFile.zoomLevels[n].width, - rmapFile.zoomLevels[n].height, rmapFile.zoomLevels[n].xTiles, rmapFile.zoomLevels[n].yTiles, + log.trace(String.format("zoomLevels[%d] zoom=%d %dx%d pixels, %dx%d tiles %s", rmapFile.zoomLevels[n].index, + rmapFile.zoomLevels[n].zoom, rmapFile.zoomLevels[n].width, rmapFile.zoomLevels[n].height, + rmapFile.zoomLevels[n].xTiles, rmapFile.zoomLevels[n].yTiles, rmapFile.zoomLevels[n].dl == false ? "calc" : "dl")); } @@ -466,8 +235,9 @@ public class TwoNavRMAP extends AtlasCreator { if ((map.getMapSource().getTileImageType() != TileImageType.JPG) || (map.getParameters() != null)) { // Tiles have to be converted to jpeg format TileImageFormat imageFormat = TileImageFormat.JPEG90; - if (map.getParameters() != null) + if (map.getParameters() != null) { imageFormat = map.getParameters().getFormat(); + } mapDlTileProvider = new ConvertedRawTileProvider(mapDlTileProvider, imageFormat); } @@ -513,7 +283,7 @@ public class TwoNavRMAP extends AtlasCreator { try { rmapFile.setLength(0); } finally { - Utilities.closeFile(rmapFile); + Utilities.closeQuietly(rmapFile); } super.abortAtlasCreation(); } @@ -544,4 +314,228 @@ public class TwoNavRMAP extends AtlasCreator { super.finishLayerCreation(); } + private class ZoomLevel { + + private int index = 0; + private long offset = 0; + private int width = 0; + private int height = 0; + private int xTiles = 0; + private int yTiles = 0; + private long[][] jpegOffsets = null; + private int zoom = 0; + private boolean dl = false; + + private void writeHeader() throws IOException { + if (offset == 0) { + offset = rmapFile.getFilePointer(); + } else { + rmapFile.seek(offset); + } + log.trace(String.format("Writing ZoomLevel %d (%dx%d pixels, %dx%d tiles) header at offset %d", index, + width, height, xTiles, yTiles, offset)); + rmapFile.writeIntI(width); + rmapFile.writeIntI(-height); + rmapFile.writeIntI(xTiles); + rmapFile.writeIntI(yTiles); + if (jpegOffsets == null) { + jpegOffsets = new long[xTiles][yTiles]; + } + for (int y = 0; y < yTiles; y++) { + for (int x = 0; x < xTiles; x++) { + rmapFile.writeLongI(jpegOffsets[x][y]); + } + } + } + + private BufferedImage loadJpegAtOffset(long offset) throws IOException { + if (offset == 0) { + throw new IOException("offset == 0"); + } + rmapFile.seek(offset); + int TagId = rmapFile.readIntI(); + if (TagId != 7) { + throw new IOException("TagId != 7"); + } + int TagLen = rmapFile.readIntI(); + byte[] jpegImageBuf = new byte[TagLen]; + rmapFile.readFully(jpegImageBuf); + ByteArrayInputStream input = new ByteArrayInputStream(jpegImageBuf); + return ImageIO.read(input); + } + + private byte[] getTileData(TileImageDataWriter writer, ZoomLevel source, int x, int y) throws IOException { + log.trace("Shrinking jpegs ({},{},{} - {},{},{})", source.index, x, y, source.index, + (x + 1 < source.xTiles) ? x + 1 : x, (y + 1 < source.yTiles) ? y + 1 : y); + BufferedImage bi11 = loadJpegAtOffset(source.jpegOffsets[x][y]); + BufferedImage bi21 = (x + 1 < source.xTiles) ? loadJpegAtOffset(source.jpegOffsets[x + 1][y]) : null; + BufferedImage bi12 = (y + 1 < source.yTiles) ? loadJpegAtOffset(source.jpegOffsets[x][y + 1]) : null; + BufferedImage bi22 = (x + 1 < source.xTiles) && (y + 1 < source.yTiles) + ? loadJpegAtOffset(source.jpegOffsets[x + 1][y + 1]) + : null; + int biWidth = bi11.getWidth() + (bi21 != null ? bi21.getWidth() : 0); + int biHeight = bi11.getHeight() + (bi12 != null ? bi12.getHeight() : 0); + BufferedImage bi = new BufferedImage(biWidth, biHeight, BufferedImage.TYPE_3BYTE_BGR); + Graphics2D g = bi.createGraphics(); + g.drawImage(bi11, 0, 0, null); + if (bi21 != null) { + g.drawImage(bi21, bi11.getWidth(), 0, null); + } + if (bi12 != null) { + g.drawImage(bi12, 0, bi11.getHeight(), null); + } + if (bi22 != null) { + g.drawImage(bi22, bi11.getWidth(), bi11.getHeight(), null); + } + AffineTransformOp op = new AffineTransformOp(new AffineTransform(0.5, 0, 0, 0.5, 0, 0), + AffineTransformOp.TYPE_BILINEAR); + BufferedImage biOut = new BufferedImage(biWidth / 2, biHeight / 2, BufferedImage.TYPE_3BYTE_BGR); + op.filter(bi, biOut); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(biOut.getWidth() * biOut.getHeight() * 4); + writer.processImage(biOut, buffer); + g.dispose(); + return buffer.toByteArray(); + } + + private void shrinkFrom(ZoomLevel source) { + try (TileImageDataWriter writer = new TileImageJpegDataWriter(0.9)) { + writeHeader(); + atlasProgress.initMapCreation(xTiles * yTiles); + for (int x = 0; x < xTiles; x++) { + for (int y = 0; y < yTiles; y++) { + checkUserAbort(); + atlasProgress.incMapCreationProgress(); + jpegOffsets[x][y] = rmapFile.getFilePointer(); + byte[] tileData = getTileData(writer, source, 2 * x, 2 * y); + rmapFile.seek(jpegOffsets[x][y]); + log.trace("Writing shrunken jpeg ({},{},{}) at offset {}", index, x, y, jpegOffsets[x][y]); + rmapFile.writeIntI(7); + rmapFile.writeIntI(tileData.length); + rmapFile.write(tileData); + } + } + } catch (Exception e) { + log.error("Failed generating ZoomLevel {}: {}", index, e.getMessage()); + } + } + } + + private class RmapFile extends RandomAccessFile { + + private final String name; + private int width = 0; + private int height = 0; + private int tileWidth = 0; + private int tileHeight = 0; + private double longitudeMin = 0; + private double longitudeMax = 0; + private double latitudeMin = 0; + private double latitudeMax = 0; + private long mapDataOffset = 0; + private ZoomLevel[] zoomLevels = null; + + private RmapFile(File file) throws FileNotFoundException { + super(file, "rw"); + this.name = file.getName(); + } + + private int readIntI() throws IOException { + int ch1 = this.read(); + int ch2 = this.read(); + int ch3 = this.read(); + int ch4 = this.read(); + if ((ch1 | ch2 | ch3 | ch4) < 0) { + throw new IOException(); + } + return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1)); + } + + private void writeIntI(int i) throws IOException { + write((i) & 0xFF); + write((i >>> 8) & 0xFF); + write((i >>> 16) & 0xFF); + write((i >>> 24) & 0xFF); + } + + private void writeLongI(long l) throws IOException { + write((int) (l) & 0xFF); + write((int) (l >>> 8) & 0xFF); + write((int) (l >>> 16) & 0xFF); + write((int) (l >>> 24) & 0xFF); + write((int) (l >>> 32) & 0xFF); + write((int) (l >>> 40) & 0xFF); + write((int) (l >>> 48) & 0xFF); + write((int) (l >>> 56) & 0xFF); + } + + private void writeHeader() throws IOException { + log.trace("Writing rmap header"); + if (zoomLevels == null) { + throw new IOException("zoomLevels == null"); + } + seek(0); + write("CompeGPSRasterImage".getBytes()); + writeIntI(10); + writeIntI(7); + writeIntI(0); + writeIntI(width); + writeIntI(-height); + writeIntI(24); + writeIntI(1); + writeIntI(tileWidth); + writeIntI(tileHeight); + writeLongI(mapDataOffset); + writeIntI(0); + writeIntI(zoomLevels.length); + for (int n = 0; n < zoomLevels.length; n++) { + writeLongI(zoomLevels[n].offset); + } + } + + private void writeMapInfo() throws IOException { + if (mapDataOffset == 0) { + mapDataOffset = getFilePointer(); + } else { + seek(mapDataOffset); + } + log.trace("Writing MAP data at offset {}", mapDataOffset); + StringBuffer sbMap = new StringBuffer(); + sbMap.append("CompeGPS MAP File\r\n"); + sbMap.append("
      \r\n"); + sbMap.append("Version=2\r\n"); + sbMap.append("VerCompeGPS=MOBAC\r\n"); + sbMap.append("Projection=2,Mercator,\r\n"); + sbMap.append("Coordinates=1\r\n"); + sbMap.append("Datum=WGS 84\r\n"); + sbMap.append("
      \r\n"); + sbMap.append("\r\n"); + sbMap.append("Bitmap=" + name + "\r\n"); + sbMap.append("BitsPerPixel=0\r\n"); + sbMap.append(String.format("BitmapWidth=%d\r\n", width)); + sbMap.append(String.format("BitmapHeight=%d\r\n", height)); + sbMap.append("Type=10\r\n"); + sbMap.append("\r\n"); + sbMap.append("\r\n"); + String pointLine = "P%d=%d,%d,A,%s,%s\r\n"; + DecimalFormat df = (DecimalFormat) NumberFormat.getNumberInstance(Locale.US); + df.applyPattern("#0.00000000"); + sbMap.append(String.format(pointLine, 0, 0, 0, df.format(longitudeMin), df.format(latitudeMax))); + sbMap.append(String.format(pointLine, 1, width - 1, 0, df.format(longitudeMax), df.format(latitudeMax))); + sbMap.append(String.format(pointLine, 2, width - 1, height - 1, df.format(longitudeMax), + df.format(latitudeMin))); + sbMap.append(String.format(pointLine, 3, 0, height - 1, df.format(longitudeMin), df.format(latitudeMin))); + sbMap.append("\r\n"); + sbMap.append("\r\n"); + String polyLine = "M%d=%d,%d\r\n"; + sbMap.append(String.format(polyLine, 0, 0, 0)); + sbMap.append(String.format(polyLine, 1, width, 0)); + sbMap.append(String.format(polyLine, 2, width, height)); + sbMap.append(String.format(polyLine, 3, 0, height)); + sbMap.append("\r\n"); + writeIntI(1); + writeIntI(sbMap.length()); + write(sbMap.toString().getBytes()); + } + } + } diff --git a/src/main/java/mobac/program/atlascreators/Ublox.java b/mobac/src/main/java/mobac/program/atlascreators/Ublox.java similarity index 86% rename from src/main/java/mobac/program/atlascreators/Ublox.java rename to mobac/src/main/java/mobac/program/atlascreators/Ublox.java index 62fd351..0403358 100644 --- a/src/main/java/mobac/program/atlascreators/Ublox.java +++ b/mobac/src/main/java/mobac/program/atlascreators/Ublox.java @@ -1,21 +1,24 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; +import mobac.program.annotations.AtlasCreatorName; +import mobac.program.interfaces.MapSpace; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -23,24 +26,15 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.util.Locale; -import mobac.program.annotations.AtlasCreatorName; -import mobac.program.interfaces.MapSpace; -import mobac.utilities.Utilities; - - @AtlasCreatorName("Ublox") public class Ublox extends Ozi { @Override protected void writeMapFile() { - FileOutputStream fout = null; - try { - fout = new FileOutputStream(new File(layerDir, mapName + ".mcf")); - writeMapFile(map.getName(), fout); + try (OutputStream out = new FileOutputStream(new File(layerDir, mapName + ".mcf"))) { + writeMapFile(map.getName(), out); } catch (Exception e) { log.error("", e); - } finally { - Utilities.closeStream(fout); } } @@ -79,10 +73,8 @@ public class Ublox extends Ozi { mcfWriter.write("[REFERENCE]\r\n"); mcfWriter.write(String.format(Locale.ENGLISH, refFmt, 1, 0, 0, longitudeMin, latitudeMax)); - mcfWriter.write(String.format(Locale.ENGLISH, refFmt, 2, width, height, longitudeMax, - latitudeMin)); - mcfWriter.write(String.format(Locale.ENGLISH, refFmt, 3, width, 0, longitudeMax, - latitudeMax)); + mcfWriter.write(String.format(Locale.ENGLISH, refFmt, 2, width, height, longitudeMax, latitudeMin)); + mcfWriter.write(String.format(Locale.ENGLISH, refFmt, 3, width, 0, longitudeMax, latitudeMax)); mcfWriter.flush(); } } diff --git a/src/main/java/mobac/program/atlascreators/Viewranger.java b/mobac/src/main/java/mobac/program/atlascreators/Viewranger.java similarity index 77% rename from src/main/java/mobac/program/atlascreators/Viewranger.java rename to mobac/src/main/java/mobac/program/atlascreators/Viewranger.java index 3571d53..635f300 100644 --- a/src/main/java/mobac/program/atlascreators/Viewranger.java +++ b/mobac/src/main/java/mobac/program/atlascreators/Viewranger.java @@ -1,23 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators; -import java.io.File; - import mobac.exceptions.AtlasTestException; import mobac.program.annotations.AtlasCreatorName; import mobac.program.annotations.SupportedParameters; @@ -29,11 +27,13 @@ import mobac.program.interfaces.MapInterface; import mobac.program.model.TileImageParameters.Name; import mobac.program.model.TileImageType; +import java.io.File; + /** * http://sourceforge.net/p/mobac/feature-requests/219/ */ @AtlasCreatorName("Viewranger") -@SupportedParameters(names = { Name.format_png }) +@SupportedParameters(names = {Name.format_png}) public class Viewranger extends OSMTracker { public Viewranger() { @@ -45,16 +45,20 @@ public class Viewranger extends OSMTracker { protected void testAtlas() throws AtlasTestException { for (LayerInterface layer : atlas) { for (MapInterface map : layer) { - if (map.getParameters() == null) + if (map.getParameters() == null) { continue; - if (!TileImageType.PNG.equals(map.getParameters().getFormat().getType())) + } + if (!TileImageType.PNG.equals(map.getParameters().getFormat().getType())) { throw new AtlasTestException("Only PNG output format allowed for Viewranger", map); - if (map.getZoom() > 18) - throw new AtlasTestException("Unsupported zoom level: " + map.getZoom() - + "\nMaximum supported zoom level is 18", map); - if (map.getZoom() < 3) - throw new AtlasTestException("Unsupported zoom level: " + map.getZoom() - + "\nMinimum suupported toom level is 3", map); + } + if (map.getZoom() > 18) { + throw new AtlasTestException( + "Unsupported zoom level: " + map.getZoom() + "\nMaximum supported zoom level is 18", map); + } + if (map.getZoom() < 3) { + throw new AtlasTestException( + "Unsupported zoom level: " + map.getZoom() + "\nMinimum supported zoom level is 3", map); + } } } } @@ -64,10 +68,11 @@ public class Viewranger extends OSMTracker { super.initializeMap(map, mapTileProvider); mapDir = new File(atlasDir, map.getLayer().getName()); tileType = ""; - if (parameters == null) + if (parameters == null) { mapDlTileProvider = new PngTileProvider(mapDlTileProvider); - else + } else { mapDlTileProvider = new ConvertedRawTileProvider(mapDlTileProvider, parameters.getFormat()); + } } } diff --git a/src/main/java/mobac/program/atlascreators/impl/MapTileBuilder.java b/mobac/src/main/java/mobac/program/atlascreators/impl/MapTileBuilder.java similarity index 79% rename from src/main/java/mobac/program/atlascreators/impl/MapTileBuilder.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/MapTileBuilder.java index fc870e8..0ad0942 100644 --- a/src/main/java/mobac/program/atlascreators/impl/MapTileBuilder.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/MapTileBuilder.java @@ -1,98 +1,102 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.impl; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import javax.imageio.ImageIO; - import mobac.exceptions.MapCreationException; import mobac.program.atlascreators.AtlasCreator; import mobac.program.atlascreators.tileprovider.TileProvider; import mobac.program.interfaces.MapInterface; import mobac.program.interfaces.MapSource; import mobac.program.interfaces.TileImageDataWriter; +import mobac.program.interfaces.TileImageDataWriterBuilder; import mobac.program.model.TileImageParameters; import mobac.utilities.MyMath; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Logger; +import javax.imageio.ImageIO; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; public class MapTileBuilder { - private static final Logger log = Logger.getLogger(MapTileBuilder.class); - - private final AtlasCreator atlasCreator; - private final TileProvider mapDlTileProvider; - private final MapInterface map; - private final MapSource mapSource; - private final TileImageParameters parameters; - private final TileImageDataWriter tileImageDataWriter; - private final int tileSize; - private final int xMin; - private final int xMax; - private final int yMin; - private final int yMax; - - private final boolean useRealTileSize; - - private int realWidth; - private int realHeight; - int mergedWidth; - int mergedHeight; - + private static final Logger log = LoggerFactory.getLogger(MapTileBuilder.class); + protected final MapTileWriter mapTileWriter; final int customTileCount; final int xStart; final int yStart; final int xEnd; final int yEnd; - - protected final MapTileWriter mapTileWriter; + private final AtlasCreator atlasCreator; + private final TileProvider mapDlTileProvider; + private final MapInterface map; + private final MapSource mapSource; + private final TileImageParameters parameters; + private final TileImageDataWriterBuilder tileImageDataWriterBuilder; + private final int tileSize; + private final int xMin; + private final int xMax; + private final int yMin; + private final int yMax; + private final boolean useRealTileSize; + int mergedWidth; + int mergedHeight; + private int realWidth; + private int realHeight; + /** + * A simple local cache holding the last 10 loaded original tiles. If the custom + * tile size is smaller than 256x256 the efficiency of this cache is very high + * (~ 75% hit rate). + */ + private final CachedTile[] cache = new CachedTile[10]; + private int cachePos = 0; /** * @param atlasCreator * @param mapTileWriter * @param useRealTileSize - * affects the tile size at the left and bottom border of the map. If true those tile will - * have the size of the remaining image data available size (they can be smaller than the size - * specified). If false the tile size will be as specified by the map's - * {@link TileImageParameters}. + * affects the tile size at the left and bottom border of the map. If + * true those tile will have the size of the remaining + * image data available size (they can be smaller than the size + * specified). If false the tile size will be as + * specified by the map's {@link TileImageParameters}. */ public MapTileBuilder(AtlasCreator atlasCreator, MapTileWriter mapTileWriter, boolean useRealTileSize) { - this(atlasCreator, atlasCreator.getParameters().getFormat().getDataWriter(), mapTileWriter, useRealTileSize); + this(atlasCreator, atlasCreator.getParameters().getFormat().getDataWriterBuilder(), mapTileWriter, + useRealTileSize); } /** - * * @param atlasCreator * @param tileImageDataWriter * @param mapTileWriter * @param useRealTileSize - * affects the tile size at the left and bottom border of the map. If true those tile will - * have the size of the remaining image data available size (they can be smaller than the size - * specified). If false the tile size will be as specified by the map's - * {@link TileImageParameters}. + * affects the tile size at the left and bottom border of the map. If + * true those tile will have the size of the remaining + * image data available size (they can be smaller than the size + * specified). If false the tile size will be as + * specified by the map's {@link TileImageParameters}. */ - public MapTileBuilder(AtlasCreator atlasCreator, TileImageDataWriter tileImageDataWriter, + public MapTileBuilder(AtlasCreator atlasCreator, TileImageDataWriterBuilder tileImageDataWriter, MapTileWriter mapTileWriter, boolean useRealTileSize) { this.atlasCreator = atlasCreator; - this.tileImageDataWriter = tileImageDataWriter; + this.tileImageDataWriterBuilder = tileImageDataWriter; this.mapTileWriter = mapTileWriter; this.mapDlTileProvider = atlasCreator.getMapDlTileProvider(); this.useRealTileSize = useRealTileSize; @@ -122,10 +126,12 @@ public class MapTileBuilder { if (useRealTileSize) { // Reduce tile size of overall map height/width // if it is smaller than one tile - if (realWidth > mergedWidth) + if (realWidth > mergedWidth) { realWidth = mergedWidth; - if (realHeight > mergedHeight) + } + if (realHeight > mergedHeight) { realHeight = mergedHeight; + } } customTileCount = MyMath.divCeil(mergedWidth, realWidth) * MyMath.divCeil(mergedHeight, realHeight); } @@ -144,20 +150,22 @@ public class MapTileBuilder { // cache of ImageIO. This will speed up the creation process a bit ImageIO.setUseCache(false); ByteArrayOutputStream buf = new ByteArrayOutputStream(32768); - tileImageDataWriter.initialize(); + int currentTileHeight = realHeight; int currentTileWidth = realWidth; - try { + try (TileImageDataWriter tileImageDataWriter = tileImageDataWriterBuilder.build()) { String tileType = tileImageDataWriter.getType().getFileExt(); int tiley = 0; while (yAbsPos < yEnd) { int tilex = 0; xAbsPos = xStart; - if (useRealTileSize) + if (useRealTileSize) { currentTileHeight = Math.min(realHeight, yEnd - yAbsPos + 1); + } while (xAbsPos < xEnd) { - if (useRealTileSize) + if (useRealTileSize) { currentTileWidth = Math.min(realWidth, xEnd - xAbsPos + 1); + } atlasCreator.checkUserAbort(); atlasCreator.getAtlasProgress().incMapCreationProgress(); BufferedImage tileImage = new BufferedImage(currentTileWidth, currentTileHeight, @@ -180,8 +188,6 @@ public class MapTileBuilder { tiley++; yAbsPos += realHeight; } - } finally { - tileImageDataWriter.dispose(); } } @@ -191,9 +197,10 @@ public class MapTileBuilder { } /** - * Paints the graphics of the custom tile specified by the pixel coordinates xAbsPos and - * yAbsPos on the currently selected map & layer. - * + * Paints the graphics of the custom tile specified by the pixel coordinates + * xAbsPos and yAbsPos on the currently selected map & + * layer. + * * @param graphics * @param xAbsPos * @param yAbsPos @@ -209,8 +216,8 @@ public class MapTileBuilder { try { BufferedImage orgTileImage = loadOriginalMapTile(xTile, yTile); if (orgTileImage != null) { - //int w = orgTileImage.getWidth(); - //int h = orgTileImage.getHeight(); + // int w = orgTileImage.getWidth(); + // int h = orgTileImage.getHeight(); graphics.drawImage(orgTileImage, xTileOffset, yTileOffset, tileSize, tileSize, null); } } catch (Exception e) { @@ -228,17 +235,11 @@ public class MapTileBuilder { return customTileCount; } - /** - * A simple local cache holding the last 10 loaded original tiles. If the custom tile size is smaller than 256x256 - * the efficiency of this cache is very high (~ 75% hit rate). - */ - private CachedTile[] cache = new CachedTile[10]; - private int cachePos = 0; - private BufferedImage loadOriginalMapTile(int xTile, int yTile) throws Exception { for (CachedTile ct : cache) { - if (ct == null) + if (ct == null) { continue; + } if (ct.xTile == xTile && ct.yTile == yTile) { // log.trace("cache hit"); return ct.image; @@ -246,8 +247,9 @@ public class MapTileBuilder { } // log.trace("cache miss"); BufferedImage image = mapDlTileProvider.getTileImage(xTile, yTile); - if (image == null) + if (image == null) { return null; + } cache[cachePos] = new CachedTile(image, xTile, yTile); cachePos = (cachePos + 1) % cache.length; return image; diff --git a/src/main/java/mobac/program/atlascreators/impl/MapTileWriter.java b/mobac/src/main/java/mobac/program/atlascreators/impl/MapTileWriter.java similarity index 81% rename from src/main/java/mobac/program/atlascreators/impl/MapTileWriter.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/MapTileWriter.java index fed9936..bbaeeab 100644 --- a/src/main/java/mobac/program/atlascreators/impl/MapTileWriter.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/MapTileWriter.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.impl; @@ -21,7 +21,6 @@ import java.io.IOException; public interface MapTileWriter { /** - * * @param tilex * x tile number regarding regarding the currently processed map * (0..mapWidth / tileWidth)] @@ -32,9 +31,8 @@ public interface MapTileWriter { * @param tileData * @throws IOException */ - public void writeTile(int tilex, int tiley, String tileType, byte[] tileData) - throws IOException; + void writeTile(int tilex, int tiley, String tileType, byte[] tileData) throws IOException; - public void finalizeMap() throws IOException; + void finalizeMap() throws IOException; } diff --git a/src/main/java/mobac/program/atlascreators/impl/aqm/FlatPackCreator.java b/mobac/src/main/java/mobac/program/atlascreators/impl/aqm/FlatPackCreator.java similarity index 67% rename from src/main/java/mobac/program/atlascreators/impl/aqm/FlatPackCreator.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/aqm/FlatPackCreator.java index 2649da8..6c9ac9e 100644 --- a/src/main/java/mobac/program/atlascreators/impl/aqm/FlatPackCreator.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/aqm/FlatPackCreator.java @@ -1,39 +1,42 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.impl.aqm; +import mobac.utilities.Utilities; +import org.apache.commons.io.FileUtils; + +import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.io.OutputStreamWriter; - -import mobac.utilities.Charsets; -import mobac.utilities.Utilities; +import java.nio.charset.StandardCharsets; public class FlatPackCreator { public static final String FLAT_PACK_HEADER = "FLATPACK1"; - public static final int FILE_COPY_BUFFER_LEN = 4096 * 10; + public static final int FILE_COPY_BUFFER_LEN = 32768; private String packPath = null; - private FileOutputStream dataStream = null; + private OutputStream dataStream = null; private ByteArrayOutputStream structBuffer = null; @@ -50,12 +53,13 @@ public class FlatPackCreator { public FlatPackCreator(final String packPath) throws FileNotFoundException { this.packPath = packPath; - if (packPath == null) + if (packPath == null) { throw new NullPointerException("Pack file path is null."); + } - dataStream = new FileOutputStream(packPath + ".tmp"); + dataStream = new BufferedOutputStream(new FileOutputStream(packPath + ".tmp"), 16384); structBuffer = new ByteArrayOutputStream(); - structBufferWriter = new OutputStreamWriter(structBuffer, Charsets.ISO_8859_1); + structBufferWriter = new OutputStreamWriter(structBuffer, StandardCharsets.ISO_8859_1); currentDataWritedSize = 0; currentNbFiles = 0; @@ -71,40 +75,37 @@ public class FlatPackCreator { public final void add(final File filePath, final String fileEntryName) throws IOException { // read file content - FileInputStream in = new FileInputStream(filePath); - byte[] buff = new byte[(int) filePath.length()]; - int read = in.read(buff); - in.close(); - - if (filePath.length() != read) - throw new IOException("Error reading '" + filePath + "'."); + byte[] buff = FileUtils.readFileToByteArray(filePath); add(buff, fileEntryName); } public final void add(final byte[] buff, final String fileEntryName) throws IOException { - if (dataStream == null) + if (dataStream == null) { throw new IOException("Write stream is null."); + } // write file size - String fileSize = Integer.toString(buff.length) + "\0"; - dataStream.write(fileSize.getBytes(Charsets.ISO_8859_1)); + String fileSize = buff.length + "\0"; + dataStream.write(fileSize.getBytes(StandardCharsets.ISO_8859_1)); // write file into pack data - if (buff.length > 0) + if (buff.length > 0) { dataStream.write(buff); + } // write file into pack structure structBufferWriter.append(fileEntryName + "\0" + currentDataWritedSize + "\0"); - // update writed size + // update written size currentDataWritedSize += buff.length + fileSize.length(); currentNbFiles++; } public final void close() throws IOException { - if (dataStream == null) + if (dataStream == null) { throw new NullPointerException("Write stream is null."); + } // close data file dataStream.flush(); @@ -113,21 +114,20 @@ public class FlatPackCreator { File tmpFile = new File(packPath + ".tmp"); // open pack file - FileOutputStream packStream = new FileOutputStream(packPath); - try { - String nbFiles = Long.toString(currentNbFiles) + "\0"; + try (OutputStream packStream = new BufferedOutputStream(new FileOutputStream(packPath))) { + String nbFiles = currentNbFiles + "\0"; // write header - packStream.write(FLAT_PACK_HEADER.getBytes(Charsets.ISO_8859_1)); + packStream.write(FLAT_PACK_HEADER.getBytes(StandardCharsets.ISO_8859_1)); // write struct structBufferWriter.flush(); structBufferWriter.close(); int headerSize = structBuffer.size() + nbFiles.length(); - packStream.write(Integer.toString(headerSize).getBytes(Charsets.ISO_8859_1)); + packStream.write(Integer.toString(headerSize).getBytes(StandardCharsets.ISO_8859_1)); packStream.write('\0'); - packStream.write(nbFiles.getBytes(Charsets.ISO_8859_1)); + packStream.write(nbFiles.getBytes(StandardCharsets.ISO_8859_1)); structBuffer.writeTo(packStream); @@ -136,26 +136,22 @@ public class FlatPackCreator { structBuffer = null; // write data - FileInputStream in = new FileInputStream(tmpFile); - try { + try (FileInputStream in = new FileInputStream(tmpFile)) { byte[] buffer = new byte[FILE_COPY_BUFFER_LEN]; int read; - while ((read = in.read(buffer)) > 0) + while ((read = in.read(buffer)) > 0) { packStream.write(buffer, 0, read); + } - packStream.flush(); - packStream.close(); - } finally { - Utilities.closeStream(in); } - } finally { - Utilities.closeStream(packStream); + packStream.flush(); } // delete temp file - if (tmpFile.isFile()) + if (tmpFile.isFile()) { Utilities.deleteFile(tmpFile); + } // reset state packPath = null; diff --git a/src/main/java/mobac/program/atlascreators/impl/gemf/GEMFFileCreator.java b/mobac/src/main/java/mobac/program/atlascreators/impl/gemf/GEMFFileCreator.java similarity index 58% rename from src/main/java/mobac/program/atlascreators/impl/gemf/GEMFFileCreator.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/gemf/GEMFFileCreator.java index ab36e49..d7066ec 100644 --- a/src/main/java/mobac/program/atlascreators/impl/gemf/GEMFFileCreator.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/gemf/GEMFFileCreator.java @@ -1,391 +1,394 @@ -/******************************************************************************* - * Copyright (c) MOBAC developers - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - ******************************************************************************/ -/** - * - */ -package mobac.program.atlascreators.impl.gemf; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.TreeSet; - -import org.apache.log4j.Logger; - -/** - * GEMF File creator class. - * - * Reference about GEMF format: https://sites.google.com/site/abudden/android-map-store - * - * @author A. S. Budden - * @author Erik Burrows - * - * This class is a stripped-down version of the GEMFFile.java class at: - * http://code.google.com/p/osmdroid/source/ - * browse/trunk/osmdroid-android/src/main/java/org/osmdroid/util/GEMFFile.java - * - * (Date: Wed, 11th of April 2012) - * - * The original GEMFFile.java from above has been reduced to the functionality of writing a GEMF archive, as - * reading the archive seems not to be necessary. - * - * @author M. Reiter - * - */ -public class GEMFFileCreator { - private static final long FILE_SIZE_LIMIT = 1 * 1024 * 1024 * 1024; // 1GB - private static final int FILE_COPY_BUFFER_SIZE = 1024; - - private static final int VERSION = 4; - private static final int TILE_SIZE = 256; - - private static final int U32_SIZE = 4; - private static final int U64_SIZE = 8; - - /* - * Constructor to create new GEMF file from directory of sources/tiles. - * - * @param pLocation String object representing path to first GEMF archive file. Additional files (if archive size - * exceeds FILE_SIZE_LIMIT will be created with numerical suffixes, eg: test.gemf-1, test.gemf-2. - * - * @param pSourceFolders Each specified folder will be imported into the GEMF archive as a seperate source. The name - * of the folder will be the name of the source in the archive. - */ - public GEMFFileCreator(final String pLocation, final List pSourceFolders, Logger log) throws FileNotFoundException, - IOException { - - /** - *
      -		 * 1. For each source folder
      -		 *   1. Create array of zoom levels, X rows, Y rows
      -		 * 2. Build index data structure index[source][zoom][range]
      -		 *   1. For each S-Z-X find list of Ys values
      -		 *   2. For each S-Z-X-Ys set, find complete X ranges
      -		 *   3. For each S-Z-Xr-Ys set, find complete Y ranges, create Range record
      -		 * 3. Write out index
      -		 *   1. Header
      -		 *   2. Sources
      -		 *   3. For each Range
      -		 *     1. Write Range record
      -		 * 4. For each Range record
      -		 *   1. For each Range entry
      -		 *     1. If over file size limit, start new data file
      -		 *   2. Write tile data
      -		 * 
      - */ - - // this.mLocation = pLocation; - - // Create in-memory array of sources, X and Y values. - final LinkedHashMap>>> dirIndex = new LinkedHashMap>>>(); - - for (final File sourceDir : pSourceFolders) { - - final LinkedHashMap>> zList = new LinkedHashMap>>(); - - for (final File zDir : sourceDir.listFiles()) { - // Make sure the directory name is just a number - try { - Integer.parseInt(zDir.getName()); - } catch (final NumberFormatException e) { - continue; - } - - final LinkedHashMap> xList = new LinkedHashMap>(); - - for (final File xDir : zDir.listFiles()) { - - // Make sure the directory name is just a number - try { - Integer.parseInt(xDir.getName()); - } catch (final NumberFormatException e) { - continue; - } - - final LinkedHashMap yList = new LinkedHashMap(); - for (final File yFile : xDir.listFiles()) { - - try { - Integer.parseInt(yFile.getName().substring(0, yFile.getName().indexOf('.'))); - } catch (final NumberFormatException e) { - continue; - } - - yList.put(Integer.parseInt(yFile.getName().substring(0, yFile.getName().indexOf('.'))), yFile); - } - - xList.put(new Integer(xDir.getName()), yList); - } - - zList.put(Integer.parseInt(zDir.getName()), xList); - } - - dirIndex.put(sourceDir.getName(), zList); - } - - // Create a source index list - final LinkedHashMap sourceIndex = new LinkedHashMap(); - final LinkedHashMap indexSource = new LinkedHashMap(); - int si = 0; - for (final String source : dirIndex.keySet()) { - sourceIndex.put(source, new Integer(si)); - indexSource.put(new Integer(si), source); - ++si; - } - - // Create the range objects - final List ranges = new ArrayList(); - - for (final String source : dirIndex.keySet()) { - for (final Integer zoom : dirIndex.get(source).keySet()) { - - // Get non-contiguous Y sets for each Z/X - final LinkedHashMap, List> ySets = new LinkedHashMap, List>(); - - for (final Integer x : new TreeSet(dirIndex.get(source).get(zoom).keySet())) { - - final List ySet = new ArrayList(); - for (final Integer y : dirIndex.get(source).get(zoom).get(x).keySet()) { - ySet.add(y); - } - - if (ySet.size() == 0) { - continue; - } - - Collections.sort(ySet); - - if (!ySets.containsKey(ySet)) { - ySets.put(ySet, new ArrayList()); - } - - ySets.get(ySet).add(x); - } - - // For each Y set find contiguous X sets - final LinkedHashMap, List> xSets = new LinkedHashMap, List>(); - - for (final List ySet : ySets.keySet()) { - - final TreeSet xList = new TreeSet(ySets.get(ySet)); - - List xSet = new ArrayList(); - for (int i = xList.first(); i < xList.last() + 1; ++i) { - if (xList.contains(new Integer(i))) { - xSet.add(new Integer(i)); - } else { - if (xSet.size() > 0) { - xSets.put(ySet, xSet); - xSet = new ArrayList(); - } - } - } - - if (xSet.size() > 0) { - xSets.put(ySet, xSet); - } - } - - // For each contiguous X set, find contiguous Y sets and create GEMFRange object - for (final List xSet : xSets.keySet()) { - - final TreeSet yList = new TreeSet(xSet); - final TreeSet xList = new TreeSet(ySets.get(xSet)); - - GEMFRange range = new GEMFRange(); - range.zoom = zoom; - range.sourceIndex = sourceIndex.get(source); - range.xMin = xList.first(); - range.xMax = xList.last(); - - for (int i = yList.first(); i < yList.last() + 1; ++i) { - if (yList.contains(new Integer(i))) { - if (range.yMin == null) { - range.yMin = i; - } - range.yMax = i; - } else { - - if (range.yMin != null) { - ranges.add(range); - - range = new GEMFRange(); - range.zoom = zoom; - range.sourceIndex = sourceIndex.get(source); - range.xMin = xList.first(); - range.xMax = xList.last(); - } - } - } - - if (range.yMin != null) { - ranges.add(range); - } - } - } - } - - // Calculate size of header for computation of data offsets - int source_list_size = 0; - for (final String source : sourceIndex.keySet()) { - source_list_size += (U32_SIZE + U32_SIZE + source.length()); - } - - long offset = U32_SIZE + // GEMF Version - U32_SIZE + // Tile size - U32_SIZE + // Number of sources - source_list_size + ranges.size() * ((U32_SIZE * 6) + U64_SIZE) + U32_SIZE; // Number of ranges - - // Calculate offset for each range in the data set - for (final GEMFRange range : ranges) { - range.offset = offset; - - for (int x = range.xMin; x < range.xMax + 1; ++x) { - for (int y = range.yMin; y < range.yMax + 1; ++y) { - offset += (U32_SIZE + U64_SIZE); - } - } - } - - final long headerSize = offset; - - RandomAccessFile gemfFile = new RandomAccessFile(pLocation, "rw"); - - // Write version header - gemfFile.writeInt(VERSION); - - // Write file size header - gemfFile.writeInt(TILE_SIZE); - - // Write number of sources - gemfFile.writeInt(sourceIndex.size()); - - // Write source list - for (final String source : sourceIndex.keySet()) { - gemfFile.writeInt(sourceIndex.get(source)); - gemfFile.writeInt(source.length()); - gemfFile.write(source.getBytes()); - } - - // Write number of ranges - gemfFile.writeInt(ranges.size()); - - // Write range objects - for (final GEMFRange range : ranges) { - gemfFile.writeInt(range.zoom); - gemfFile.writeInt(range.xMin); - gemfFile.writeInt(range.xMax); - gemfFile.writeInt(range.yMin); - gemfFile.writeInt(range.yMax); - gemfFile.writeInt(range.sourceIndex); - gemfFile.writeLong(range.offset); - } - - // Write file offset list - for (final GEMFRange range : ranges) { - for (int x = range.xMin; x < range.xMax + 1; ++x) { - for (int y = range.yMin; y < range.yMax + 1; ++y) { - gemfFile.writeLong(offset); - - long fileSize = 0; - try { - fileSize = dirIndex.get(indexSource.get(range.sourceIndex)).get(range.zoom).get(x).get(y).length(); - } catch (NullPointerException e) { - //dont' do anything here. Error will be logged later. - } - gemfFile.writeInt((int) fileSize); - offset += fileSize; - } - } - } - - // - // Write tiles - // - - final byte[] buf = new byte[FILE_COPY_BUFFER_SIZE]; - - long currentOffset = headerSize; - int fileIndex = 0; - - for (final GEMFRange range : ranges) { - for (int x = range.xMin; x < range.xMax + 1; ++x) { - for (int y = range.yMin; y < range.yMax + 1; ++y) { - - long fileSize = 0; - try { - fileSize = dirIndex.get(indexSource.get(range.sourceIndex)).get(range.zoom).get(x).get(y).length(); - } catch (NullPointerException e) { - //don't do anything here. Error will be logged later. - } - - if (currentOffset + fileSize > FILE_SIZE_LIMIT) { - gemfFile.close(); - ++fileIndex; - gemfFile = new RandomAccessFile(pLocation + "-" + fileIndex, "rw"); - currentOffset = 0; - } else { - currentOffset += fileSize; - } - - try { - final FileInputStream tile = new FileInputStream(dirIndex.get(indexSource.get(range.sourceIndex)).get(range.zoom).get(x).get(y)); - - int read = tile.read(buf, 0, FILE_COPY_BUFFER_SIZE); - while (read != -1) { - gemfFile.write(buf, 0, read); - read = tile.read(buf, 0, FILE_COPY_BUFFER_SIZE); - } - - tile.close(); - } catch (Exception e) { - log.warn("Please check that all required Tiles have been downloaded correctly. I am missing tile for x=" + x + ", y=" + y + ", z=" + range.zoom); - } - } - } - } - - gemfFile.close(); - - // Complete construction of GEMFFile object - // openFiles(); - // readHeader(); - } - - // Class to represent a range of stored tiles within the archive. - private class GEMFRange { - Integer zoom; - Integer xMin; - Integer xMax; - Integer yMin; - Integer yMax; - Integer sourceIndex; - Long offset; - - @Override - public String toString() { - return String.format("GEMF Range: source=%d, zoom=%d, x=%d-%d, y=%d-%d, offset=0x%08X", sourceIndex, zoom, - xMin, xMax, yMin, yMax, offset); - } - }; -} +/** + * Copyright (c) MOBAC developers + *

      + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + *

      + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + *

      + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +/** + * + */ +package mobac.program.atlascreators.impl.gemf; + +import org.slf4j.Logger; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.TreeSet; + +/** + * GEMF File creator class. + * + * Reference about GEMF format: + * https://sites.google.com/site/abudden/android-map-store + * + * @author A. S. Budden + * @author Erik Burrows + * + * This class is a stripped-down version of the GEMFFile.java class at: + * http://code.google.com/p/osmdroid/source/ + * browse/trunk/osmdroid-android/src/main/java/org/osmdroid/util/GEMFFile.java + * + * (Date: Wed, 11th of April 2012) + * + * The original GEMFFile.java from above has been reduced to the + * functionality of writing a GEMF archive, as reading the archive seems + * not to be necessary. + * + * @author M. Reiter + * + */ +public class GEMFFileCreator { + private static final long FILE_SIZE_LIMIT = 1 * 1024 * 1024 * 1024; // 1GB + private static final int FILE_COPY_BUFFER_SIZE = 8192; + + private static final int VERSION = 4; + private static final int TILE_SIZE = 256; + + private static final int U32_SIZE = 4; + private static final int U64_SIZE = 8; + + /* + * Constructor to create new GEMF file from directory of sources/tiles. + * + * @param pLocation String object representing path to first GEMF archive file. + * Additional files (if archive size exceeds FILE_SIZE_LIMIT will be created + * with numerical suffixes, eg: test.gemf-1, test.gemf-2. + * + * @param pSourceFolders Each specified folder will be imported into the GEMF + * archive as a seperate source. The name of the folder will be the name of the + * source in the archive. + */ + public GEMFFileCreator(final String pLocation, final List pSourceFolders, Logger log) throws IOException { + + /** + *

      +		 * 1. For each source folder
      +		 *   1. Create array of zoom levels, X rows, Y rows
      +		 * 2. Build index data structure index[source][zoom][range]
      +		 *   1. For each S-Z-X find list of Ys values
      +		 *   2. For each S-Z-X-Ys set, find complete X ranges
      +		 *   3. For each S-Z-Xr-Ys set, find complete Y ranges, create Range record
      +		 * 3. Write out index
      +		 *   1. Header
      +		 *   2. Sources
      +		 *   3. For each Range
      +		 *     1. Write Range record
      +		 * 4. For each Range record
      +		 *   1. For each Range entry
      +		 *     1. If over file size limit, start new data file
      +		 *   2. Write tile data
      +		 * 
      + */ + + // this.mLocation = pLocation; + + // Create in-memory array of sources, X and Y values. + final LinkedHashMap>>> dirIndex = new LinkedHashMap<>(); + + for (final File sourceDir : pSourceFolders) { + + final LinkedHashMap>> zList = new LinkedHashMap<>(); + + for (final File zDir : sourceDir.listFiles()) { + // Make sure the directory name is just a number + try { + Integer.parseInt(zDir.getName()); + } catch (final NumberFormatException e) { + continue; + } + + final LinkedHashMap> xList = new LinkedHashMap<>(); + + for (final File xDir : zDir.listFiles()) { + + // Make sure the directory name is just a number + try { + Integer.parseInt(xDir.getName()); + } catch (final NumberFormatException e) { + continue; + } + + final LinkedHashMap yList = new LinkedHashMap<>(); + for (final File yFile : xDir.listFiles()) { + + try { + Integer.parseInt(yFile.getName().substring(0, yFile.getName().indexOf('.'))); + } catch (final NumberFormatException e) { + continue; + } + + yList.put(Integer.parseInt(yFile.getName().substring(0, yFile.getName().indexOf('.'))), yFile); + } + + xList.put(Integer.valueOf(xDir.getName()), yList); + } + + zList.put(Integer.parseInt(zDir.getName()), xList); + } + + dirIndex.put(sourceDir.getName(), zList); + } + + // Create a source index list + final LinkedHashMap sourceIndex = new LinkedHashMap<>(); + final LinkedHashMap indexSource = new LinkedHashMap<>(); + int si = 0; + for (final String source : dirIndex.keySet()) { + sourceIndex.put(source, si); + indexSource.put(si, source); + ++si; + } + + // Create the range objects + final List ranges = new ArrayList(); + + for (final String source : dirIndex.keySet()) { + for (final Integer zoom : dirIndex.get(source).keySet()) { + + // Get non-contiguous Y sets for each Z/X + final LinkedHashMap, List> ySets = new LinkedHashMap<>(); + + for (final Integer x : new TreeSet<>(dirIndex.get(source).get(zoom).keySet())) { + + final List ySet = new ArrayList<>(); + ySet.addAll(dirIndex.get(source).get(zoom).get(x).keySet()); + + if (ySet.isEmpty()) { + continue; + } + + Collections.sort(ySet); + + if (!ySets.containsKey(ySet)) { + ySets.put(ySet, new ArrayList<>()); + } + + ySets.get(ySet).add(x); + } + + // For each Y set find contiguous X sets + final LinkedHashMap, List> xSets = new LinkedHashMap<>(); + + for (final List ySet : ySets.keySet()) { + + final TreeSet xList = new TreeSet<>(ySets.get(ySet)); + + List xSet = new ArrayList<>(); + for (int i = xList.first(); i < xList.last() + 1; ++i) { + if (xList.contains(i)) { + xSet.add(i); + } else { + if (xSet.size() > 0) { + xSets.put(ySet, xSet); + xSet = new ArrayList<>(); + } + } + } + + if (xSet.size() > 0) { + xSets.put(ySet, xSet); + } + } + + // For each contiguous X set, find contiguous Y sets and create GEMFRange object + for (final List xSet : xSets.keySet()) { + + final TreeSet yList = new TreeSet<>(xSet); + final TreeSet xList = new TreeSet<>(ySets.get(xSet)); + + GEMFRange range = new GEMFRange(); + range.zoom = zoom; + range.sourceIndex = sourceIndex.get(source); + range.xMin = xList.first(); + range.xMax = xList.last(); + + for (int i = yList.first(); i < yList.last() + 1; ++i) { + if (yList.contains(i)) { + if (range.yMin == null) { + range.yMin = i; + } + range.yMax = i; + } else { + + if (range.yMin != null) { + ranges.add(range); + + range = new GEMFRange(); + range.zoom = zoom; + range.sourceIndex = sourceIndex.get(source); + range.xMin = xList.first(); + range.xMax = xList.last(); + } + } + } + + if (range.yMin != null) { + ranges.add(range); + } + } + } + } + + // Calculate size of header for computation of data offsets + int source_list_size = 0; + for (final String source : sourceIndex.keySet()) { + source_list_size += (U32_SIZE + U32_SIZE + source.length()); + } + + long offset = U32_SIZE + // GEMF Version + U32_SIZE + // Tile size + U32_SIZE + // Number of sources + source_list_size + ranges.size() * ((U32_SIZE * 6) + U64_SIZE) + U32_SIZE; // Number of ranges + + // Calculate offset for each range in the data set + for (final GEMFRange range : ranges) { + range.offset = offset; + + for (int x = range.xMin; x < range.xMax + 1; ++x) { + for (int y = range.yMin; y < range.yMax + 1; ++y) { + offset += (U32_SIZE + U64_SIZE); + } + } + } + + final long headerSize = offset; + + RandomAccessFile gemfFile = new RandomAccessFile(pLocation, "rw"); + try { + + // Write version header + gemfFile.writeInt(VERSION); + + // Write file size header + gemfFile.writeInt(TILE_SIZE); + + // Write number of sources + gemfFile.writeInt(sourceIndex.size()); + + // Write source list + for (final String source : sourceIndex.keySet()) { + gemfFile.writeInt(sourceIndex.get(source)); + gemfFile.writeInt(source.length()); + gemfFile.write(source.getBytes()); + } + + // Write number of ranges + gemfFile.writeInt(ranges.size()); + + // Write range objects + for (final GEMFRange range : ranges) { + gemfFile.writeInt(range.zoom); + gemfFile.writeInt(range.xMin); + gemfFile.writeInt(range.xMax); + gemfFile.writeInt(range.yMin); + gemfFile.writeInt(range.yMax); + gemfFile.writeInt(range.sourceIndex); + gemfFile.writeLong(range.offset); + } + + // Write file offset list + for (final GEMFRange range : ranges) { + for (int x = range.xMin; x < range.xMax + 1; ++x) { + for (int y = range.yMin; y < range.yMax + 1; ++y) { + gemfFile.writeLong(offset); + + long fileSize = 0; + try { + fileSize = dirIndex.get(indexSource.get(range.sourceIndex)).get(range.zoom).get(x).get(y) + .length(); + } catch (NullPointerException e) { + // dont' do anything here. Error will be logged later. + } + gemfFile.writeInt((int) fileSize); + offset += fileSize; + } + } + } + + // + // Write tiles + // + + final byte[] buf = new byte[FILE_COPY_BUFFER_SIZE]; + + long currentOffset = headerSize; + int fileIndex = 0; + + for (final GEMFRange range : ranges) { + for (int x = range.xMin; x < range.xMax + 1; ++x) { + for (int y = range.yMin; y < range.yMax + 1; ++y) { + + long fileSize = 0; + try { + fileSize = dirIndex.get(indexSource.get(range.sourceIndex)).get(range.zoom).get(x).get(y) + .length(); + } catch (NullPointerException e) { + // don't do anything here. Error will be logged later. + } + + if (currentOffset + fileSize > FILE_SIZE_LIMIT) { + gemfFile.close(); + ++fileIndex; + gemfFile = new RandomAccessFile(pLocation + "-" + fileIndex, "rw"); + currentOffset = 0; + } else { + currentOffset += fileSize; + } + + File tileFile = dirIndex.get(indexSource.get(range.sourceIndex)).get(range.zoom).get(x).get(y); + try (FileInputStream tile = new FileInputStream(tileFile)) { + int read = tile.read(buf, 0, FILE_COPY_BUFFER_SIZE); + while (read != -1) { + gemfFile.write(buf, 0, read); + read = tile.read(buf, 0, FILE_COPY_BUFFER_SIZE); + } + } catch (Exception e) { + log.warn("Please check that all required Tiles have been downloaded correctly. " + + "I am missing tile for x=" + x + ", y=" + y + ", z=" + range.zoom); + } + } + } + } + } finally { + gemfFile.close(); + } + + // Complete construction of GEMFFile object + // openFiles(); + // readHeader(); + } + + // Class to represent a range of stored tiles within the archive. + private static class GEMFRange { + Integer zoom; + Integer xMin; + Integer xMax; + Integer yMin; + Integer yMax; + Integer sourceIndex; + Long offset; + + @Override + public String toString() { + return String.format("GEMF Range: source=%d, zoom=%d, x=%d-%d, y=%d-%d, offset=0x%08X", sourceIndex, zoom, + xMin, xMax, yMin, yMax, offset); + } + } + +} diff --git a/src/main/java/mobac/program/atlascreators/impl/rmp/BoundingRect.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/BoundingRect.java similarity index 89% rename from src/main/java/mobac/program/atlascreators/impl/rmp/BoundingRect.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/rmp/BoundingRect.java index 97eda5d..0804a6a 100644 --- a/src/main/java/mobac/program/atlascreators/impl/rmp/BoundingRect.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/BoundingRect.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ /* ********************************************* * Copyright: Andreas Sander @@ -25,9 +25,8 @@ package mobac.program.atlascreators.impl.rmp; /** * Rectangle made from latitude/longitude coordinates. Negative latitude is to * the north and negative longitude is to the west. - * + * * @author Andreas Sander - * */ public class BoundingRect { private double north; @@ -79,8 +78,7 @@ public class BoundingRect { @Override public String toString() { - return String.format("BoundingRect [N=%2.4f, S==%2.4f, W=%2.4f, E=%2.4f]", north, south, - west, east); + return String.format("BoundingRect [N=%2.4f, S==%2.4f, W=%2.4f, E=%2.4f]", north, south, west, east); } } diff --git a/src/main/java/mobac/program/atlascreators/impl/rmp/ChecksumOutputStream.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/ChecksumOutputStream.java similarity index 89% rename from src/main/java/mobac/program/atlascreators/impl/rmp/ChecksumOutputStream.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/rmp/ChecksumOutputStream.java index 0a1704e..0bf0e37 100644 --- a/src/main/java/mobac/program/atlascreators/impl/rmp/ChecksumOutputStream.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/ChecksumOutputStream.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ /* ------------------------------------------------------------------------ @@ -35,16 +35,15 @@ import java.io.OutputStream; /** * OutputStream that calculates a 2Byte XOR checksum over the stream written - * */ public class ChecksumOutputStream extends OutputStream { - private OutputStream nextStream; int checksum; boolean evenByte; + private final OutputStream nextStream; /** * Constructor - * + * * @param next_stream * stream to write data to */ @@ -90,10 +89,11 @@ public class ChecksumOutputStream extends OutputStream { int o = off; for (int i = 0; i < len; i++) { - if (evenByte) + if (evenByte) { value = (((int) buf[o++]) & 0xFF) << 8; - else + } else { value = (((int) buf[o++]) & 0xFF); + } checksum ^= value; evenByte = !evenByte; @@ -112,10 +112,11 @@ public class ChecksumOutputStream extends OutputStream { public void write(int val) throws IOException { int value; - if (evenByte) + if (evenByte) { value = (val & 0xFF) << 8; - else + } else { value = (val & 0xFF); + } checksum ^= value; evenByte = !evenByte; diff --git a/src/main/java/mobac/program/atlascreators/impl/rmp/MobacTile.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/MobacTile.java similarity index 81% rename from src/main/java/mobac/program/atlascreators/impl/rmp/MobacTile.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/rmp/MobacTile.java index 3113ab4..50dcbc5 100644 --- a/src/main/java/mobac/program/atlascreators/impl/rmp/MobacTile.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/MobacTile.java @@ -1,42 +1,41 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.impl.rmp; +import mobac.program.atlascreators.tileprovider.TileProvider; +import mobac.program.interfaces.MapSpace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.Color; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.awt.image.WritableRaster; import java.io.IOException; -import mobac.program.atlascreators.tileprovider.TileProvider; -import mobac.program.interfaces.MapSpace; - -import org.apache.log4j.Logger; - - public class MobacTile { - private static final Logger log = Logger.getLogger(MobacTile.class); + private static final Logger log = LoggerFactory.getLogger(MobacTile.class); private final TileProvider tileProvider; private final int tilex; private final int tiley; private BufferedImage image; - private BoundingRect boundingRect; + private final BoundingRect boundingRect; public MobacTile(TileProvider tileProvider, MapSpace mapSpace, int tilex, int tiley, int zoom) { this.tileProvider = tileProvider; @@ -62,8 +61,9 @@ public class MobacTile { public BufferedImage getImage() { /* --- Load image if none is present --- */ - if (image == null) + if (image == null) { image = loadImage(); + } return image; } @@ -80,7 +80,7 @@ public class MobacTile { /** * create a black Tile - * + * * @return image of black square */ private BufferedImage createBlack(int width, int height) { @@ -108,12 +108,12 @@ public class MobacTile { /* --- Get Graphics context --- */ src_image = getImage(); - if (src_image == null) + if (src_image == null) { return; + } /* --- Convert it to RGB color space --- */ - imageBuffer = new BufferedImage(src_image.getWidth(), src_image.getHeight(), - BufferedImage.TYPE_INT_RGB); + imageBuffer = new BufferedImage(src_image.getWidth(), src_image.getHeight(), BufferedImage.TYPE_INT_RGB); graphics = imageBuffer.createGraphics(); try { graphics.drawImage(src_image, 0, 0, null); @@ -124,41 +124,39 @@ public class MobacTile { dst_graph = dest_image.getRaster(); /* - * --- Iterate over all pixels of the destination image. Unfortunately - * we need this technique because source and dest do not have exactly - * the same zoom level, so the source image has to be compressed or - * expanded to match the destination image --- + * --- Iterate over all pixels of the destination image. Unfortunately we need + * this technique because source and dest do not have exactly the same zoom + * level, so the source image has to be compressed or expanded to match the + * destination image --- */ maxx = dest_image.getWidth(); maxy = dest_image.getHeight(); for (int y = 0; y < maxy; y++) { /* --- Calculate the y-coordinate of the current line --- */ - src_c_y = dest_area.getNorth() + (dest_area.getSouth() - dest_area.getNorth()) * y - / maxy; + src_c_y = dest_area.getNorth() + (dest_area.getSouth() - dest_area.getNorth()) * y / maxy; /* --- Calculate the pixel line of the source image --- */ - pix_y = (int) ((src_c_y - src_area.getNorth()) * 256 - / (src_area.getSouth() - src_area.getNorth()) + 0.5); + pix_y = (int) ((src_c_y - src_area.getNorth()) * 256 / (src_area.getSouth() - src_area.getNorth()) + 0.5); /* --- Ignore line that are out of the source area --- */ - if (pix_y < 0 || pix_y > 255) + if (pix_y < 0 || pix_y > 255) { continue; + } // log.trace("scale factor y: " + (pix_y / (double) y)); for (int x = 0; x < maxx; x++) { /* --- Calculate the x-coordinate of the current row --- */ - src_c_x = dest_area.getWest() + (dest_area.getEast() - dest_area.getWest()) * x - / maxx; + src_c_x = dest_area.getWest() + (dest_area.getEast() - dest_area.getWest()) * x / maxx; /* --- Calculate the pixel row of the source image --- */ - pix_x = (int) ((src_c_x - src_area.getWest()) * 256 - / (src_area.getEast() - src_area.getWest()) + 0.5); + pix_x = (int) ((src_c_x - src_area.getWest()) * 256 / (src_area.getEast() - src_area.getWest()) + 0.5); /* --- Ignore the row if it is outside the source area --- */ - if (pix_x < 0 || pix_x > 255) + if (pix_x < 0 || pix_x > 255) { continue; + } /* --- Transfer the pixel --- */ src_graph.getPixel(pix_x, pix_y, pixel); diff --git a/src/main/java/mobac/program/atlascreators/impl/rmp/MultiImage.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/MultiImage.java similarity index 83% rename from src/main/java/mobac/program/atlascreators/impl/rmp/MultiImage.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/rmp/MultiImage.java index ec5ec33..8c99265 100644 --- a/src/main/java/mobac/program/atlascreators/impl/rmp/MultiImage.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/MultiImage.java @@ -1,47 +1,46 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.impl.rmp; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.image.BufferedImage; - import mobac.exceptions.MapCreationException; import mobac.program.atlascreators.tileprovider.TileProvider; import mobac.program.interfaces.MapInterface; import mobac.program.interfaces.MapSource; import mobac.program.interfaces.MapSpace; import mobac.utilities.collections.SoftHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Logger; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; /** * CalibratedImage that gets its data from a set of other CalibratedImage2 - * */ public class MultiImage { - private static final Logger log = Logger.getLogger(MultiImage.class); + private static final Logger log = LoggerFactory.getLogger(MultiImage.class); private final MapInterface map; private final MapSource mapSource; private final int zoom; private final TileProvider tileProvider; - private SoftHashMap cache; + private final SoftHashMap cache; public MultiImage(MapSource mapSource, TileProvider tileProvider, MapInterface map) { this.mapSource = mapSource; @@ -52,8 +51,7 @@ public class MultiImage { } public BufferedImage getSubImage(BoundingRect area, int width, int height) throws MapCreationException { - if (log.isTraceEnabled()) - log.trace(String.format("getSubImage %d %d %s", width, height, area)); + log.trace("getSubImage {} {} {}", width, height, area); MapSpace mapSpace = mapSource.getMapSpace(); int tilesize = mapSpace.getTileSize(); @@ -90,8 +88,8 @@ public class MultiImage { } protected static class TileKey { - int x; - int y; + final int x; + final int y; public TileKey(int x, int y) { this.x = x; @@ -109,18 +107,20 @@ public class MultiImage { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } TileKey other = (TileKey) obj; - if (x != other.x) + if (x != other.x) { return false; - if (y != other.y) - return false; - return true; + } + return y == other.y; } } diff --git a/src/main/java/mobac/program/atlascreators/impl/rmp/RmpLayer.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/RmpLayer.java similarity index 84% rename from src/main/java/mobac/program/atlascreators/impl/rmp/RmpLayer.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/rmp/RmpLayer.java index b8019c9..ed4014b 100644 --- a/src/main/java/mobac/program/atlascreators/impl/rmp/RmpLayer.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/RmpLayer.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ /* ********************************************* * Copyright: Andreas Sander @@ -22,6 +22,12 @@ package mobac.program.atlascreators.impl.rmp; +import mobac.gui.AtlasProgress; +import mobac.program.atlascreators.AtlasCreator; +import mobac.program.atlascreators.impl.rmp.interfaces.RmpFileEntry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -29,24 +35,14 @@ import java.io.OutputStream; import java.util.LinkedList; import java.util.List; -import mobac.gui.AtlasProgress; -import mobac.program.atlascreators.AtlasCreator; -import mobac.program.atlascreators.impl.rmp.interfaces.RmpFileEntry; - -import org.apache.log4j.Logger; - - /** * Class for building a TLM file from image and writing the file to a stream - * */ public class RmpLayer { - private static final Logger log = Logger.getLogger(RmpLayer.class); - - private List tiles; - private TLMEntry tlmFile = null; - + private static final Logger log = LoggerFactory.getLogger(RmpLayer.class); private final AtlasCreator atlasCreator; + private final List tiles; + private TLMEntry tlmFile = null; /** * Constructor @@ -65,7 +61,7 @@ public class RmpLayer { /** * Return the content of the TLM file as byte array - * + * * @throws IOException */ public TLMEntry getTLMFile(String image_name) { @@ -86,27 +82,30 @@ public class RmpLayer { int containerCount; /* - * --- Calculate the number of tiles and tiles per container. 99 would - * be possible but we limit ourselves to 80 - That's enough --- + * --- Calculate the number of tiles and tiles per container. 99 would be + * possible but we limit ourselves to 80 - That's enough --- */ int count = tiles.size(); containerCount = count / 80; - if (count % 80 != 0) + if (count % 80 != 0) { containerCount++; + } int tilesPerContainer = count / containerCount; /* --- Create containers --- */ container = new TileContainer[containerCount]; - for (int i = 0; i < containerCount; i++) + for (int i = 0; i < containerCount; i++) { container[i] = new TileContainer(); + } /* - * --- We need an index container if there is more than one container. - * Container 0 is the previous of the index container --- + * --- We need an index container if there is more than one container. Container + * 0 is the previous of the index container --- */ - if (containerCount > 1) + if (containerCount > 1) { indexContainer = new TileContainer(container[0]); + } /* --- Place the tiles into the container --- */ int tileCount = 0; @@ -114,13 +113,14 @@ public class RmpLayer { int containerNumber = 0; for (Tiledata tiledata : tiles) { /* - * --- Starting with the second container, the first element is - * moved to the index container --- + * --- Starting with the second container, the first element is moved to the + * index container --- */ - if (tileCount == 0 && containerNumber != 0) + if (tileCount == 0 && containerNumber != 0) { indexContainer.addTile(tiledata, container[containerNumber]); - else + } else { container[containerNumber].addTile(tiledata, null); + } /* --- Switch to next container if we reach end of container --- */ tileCount++; @@ -129,50 +129,49 @@ public class RmpLayer { tileCount = 0; /* - * --- Recalculate the number of tiles per container because of - * rounding issues + * --- Recalculate the number of tiles per container because of rounding issues */ - if (containerCount != containerNumber) - tilesPerContainer = (count - (totalTileCount + 1)) - / (containerCount - containerNumber); + if (containerCount != containerNumber) { + tilesPerContainer = (count - (totalTileCount + 1)) / (containerCount - containerNumber); + } } totalTileCount++; } /* - * --- If we have multiple containers, then the index container is the - * result, otherwise the single container. + * --- If we have multiple containers, then the index container is the result, + * otherwise the single container. */ - if (indexContainer == null) + if (indexContainer == null) { return container[0]; - else + } else { return indexContainer; + } } /** * Create the TLM file from the TileContainer infos - * + * * @throws IOException */ - public void buildTLMFile(double tile_width, double tile_height, double left, double right, - double top, double bottom) throws IOException { + public void buildTLMFile(double tile_width, double tile_height, double left, double right, double top, + double bottom) throws IOException { tlmFile = new TLMEntry(tile_width, tile_height, left, right, top, bottom); tlmFile.updateContent(); } public class TLMEntry implements RmpFileEntry { - private byte[] data = null; - String imageName; final double tile_width; final double tile_height; final double left; final double right; final double top; final double bottom; + String imageName; + private byte[] data = null; - public TLMEntry(double tile_width, double tile_height, double left, double right, - double top, double bottom) { + public TLMEntry(double tile_width, double tile_height, double left, double right, double top, double bottom) { super(); this.tile_width = tile_width; this.tile_height = tile_height; @@ -218,8 +217,9 @@ public class RmpLayer { int size = 256 + 1940 + 3 * 1992; size += container.getContainerCount() * 1992; - if (container.getContainerCount() != 1) + if (container.getContainerCount() != 1) { size += 1992; + } RmpTools.writeValue(bos, size, 4); // File size RmpTools.writeValue(bos, 0, 96); // Filler diff --git a/src/main/java/mobac/program/atlascreators/impl/rmp/RmpTools.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/RmpTools.java similarity index 77% rename from src/main/java/mobac/program/atlascreators/impl/rmp/RmpTools.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/rmp/RmpTools.java index bcf2f9d..0b27750 100644 --- a/src/main/java/mobac/program/atlascreators/impl/rmp/RmpTools.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/RmpTools.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ /* ********************************************* * Copyright: Andreas Sander @@ -32,7 +32,7 @@ public class RmpTools { /** * Copies the given value into the stream as binary value, with least * significant byte first. - * + * * @param stream * stream to write to * @param value @@ -54,16 +54,15 @@ public class RmpTools { int i; for (i = 0; i < length; i++) { - stream.write((int)(value & 0xFF)); + stream.write((int) (value & 0xFF)); value >>= 8; } } /** - * Writes the given string into the stream. The string is written with a - * fixed length. If the length is longer than the string, then 00 bytes are - * written - * + * Writes the given string into the stream. The string is written with a fixed + * length. If the length is longer than the string, then 00 bytes are written + * * @param stream * stream to write to * @param str @@ -72,16 +71,16 @@ public class RmpTools { * number of bytes to write * @throws IOException */ - public static void writeFixedString(OutputStream stream, String str, int length) - throws IOException { + public static void writeFixedString(OutputStream stream, String str, int length) throws IOException { int i; int value; for (i = 0; i < length; i++) { - if (i < str.length()) + if (i < str.length()) { value = str.charAt(i); - else + } else { value = 0; + } stream.write(value); } @@ -89,26 +88,25 @@ public class RmpTools { /** * Write a double value into a byte array - * + * * @param os * stream to write to * @param value * value to write */ public static void writeDouble(OutputStream os, double value) throws IOException { - ByteArrayOutputStream bo; - DataOutputStream dos; byte[] b; byte help; /* --- Convert the value into a byte array --- */ - bo = new ByteArrayOutputStream(); - dos = new DataOutputStream(bo); + try (ByteArrayOutputStream bo = new ByteArrayOutputStream()) { + try (DataOutputStream dos = new DataOutputStream(bo)) { - /* --- Convert the value into a 8 byte double --- */ - dos.writeDouble(value); - dos.close(); - b = bo.toByteArray(); + /* --- Convert the value into a 8 byte double --- */ + dos.writeDouble(value); + } + b = bo.toByteArray(); + } /* --- Change byte order --- */ for (int i = 0; i < 4; i++) { @@ -122,21 +120,23 @@ public class RmpTools { } /** - * Build an image name from a filename. The image name is the name of the - * file without path and extension . The length of the name is limited to 8 - * chars. We use only 6 chars, so we can use 99 images + * Build an image name from a filename. The image name is the name of the file + * without path and extension . The length of the name is limited to 8 chars. We + * use only 6 chars, so we can use 99 images */ public static String buildImageName(String name) { int index; /* --- Remove the extension --- */ index = name.indexOf('.'); - if (index != -1) + if (index != -1) { name = name.substring(0, index); + } /* --- Limit the filename to 8 chars --- */ - if (name.length() > 8) + if (name.length() > 8) { name = name.substring(0, 8); + } return name.toLowerCase().trim(); } @@ -151,11 +151,11 @@ public class RmpTools { indexstr = String.valueOf(index); /* - * --- cut the basename so that basename+index is not longer than 8 - * chars --- + * --- cut the basename so that basename+index is not longer than 8 chars --- */ - if (indexstr.length() + basename.length() > 8) + if (indexstr.length() + basename.length() > 8) { basename = basename.substring(0, 8 - indexstr.length()); + } return basename.trim() + indexstr; } diff --git a/src/main/java/mobac/program/atlascreators/impl/rmp/RmpWriter.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/RmpWriter.java similarity index 82% rename from src/main/java/mobac/program/atlascreators/impl/rmp/RmpWriter.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/rmp/RmpWriter.java index d0a4240..50dde83 100644 --- a/src/main/java/mobac/program/atlascreators/impl/rmp/RmpWriter.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/RmpWriter.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ /* ********************************************* * Copyright: Andreas Sander @@ -22,24 +22,23 @@ package mobac.program.atlascreators.impl.rmp; +import mobac.program.atlascreators.impl.rmp.interfaces.RmpFileEntry; +import mobac.program.atlascreators.impl.rmp.rmpfile.RmpIni; +import mobac.utilities.Utilities; +import mobac.utilities.stream.CountingOutputStream; +import mobac.utilities.stream.RandomAccessFileOutputStream; +import org.apache.commons.io.output.NullOutputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.RandomAccessFile; import java.util.ArrayList; -import mobac.program.atlascreators.impl.rmp.interfaces.RmpFileEntry; -import mobac.program.atlascreators.impl.rmp.rmpfile.RmpIni; -import mobac.utilities.Utilities; -import mobac.utilities.stream.CountingOutputStream; -import mobac.utilities.stream.RandomAccessFileOutputStream; - -import org.apache.commons.io.output.NullOutputStream; -import org.apache.log4j.Logger; - /** * Class that writes files in RMP archive format - * */ public class RmpWriter { @@ -48,14 +47,14 @@ public class RmpWriter { */ public static final long MAX_FILE_SIZE = 0xffffffffl; - private static final Logger log = Logger.getLogger(RmpWriter.class); + private static final Logger log = LoggerFactory.getLogger(RmpWriter.class); private final ArrayList entries = new ArrayList(); private final File rmpFile; private final RandomAccessFile rmpOutputFile; - private int projectedEntryCount; + private final int projectedEntryCount; - private ChecksumOutputStream entryOut; + private final ChecksumOutputStream entryOut; /** * @param imageName @@ -71,8 +70,9 @@ public class RmpWriter { // pre-calculate the number of entries: // RmpIni + (TLM & A00) per layer + Bmp2Bit + Bmp4bit this.projectedEntryCount = (3 + (2 * layerCount)); - if (rmpFile.exists()) + if (rmpFile.exists()) { Utilities.deleteFile(rmpFile); + } log.debug("Writing data to " + rmpFile.getAbsolutePath()); rmpOutputFile = new RandomAccessFile(rmpFile, "rw"); // Calculate offset to the directory end @@ -95,11 +95,13 @@ public class RmpWriter { info.offset = rmpOutputFile.getFilePointer(); entry.writeFileContent(entryOut); info.length = rmpOutputFile.getFilePointer() - info.offset; - if ((info.length % 2) != 0) + if ((info.length % 2) != 0) { entryOut.write(0); + } entries.add(info); - if (rmpOutputFile.getFilePointer() > MAX_FILE_SIZE) + if (rmpOutputFile.getFilePointer() > MAX_FILE_SIZE) { throwRmpTooLarge(); + } log.debug("Written data of entry " + entry + " bytes=" + info.length); } @@ -109,14 +111,16 @@ public class RmpWriter { info.extendsion = entry.getFileExtension(); long pos = rmpOutputFile.getFilePointer(); info.offset = pos; - CountingOutputStream cout = new CountingOutputStream(new NullOutputStream()); + CountingOutputStream cout = new CountingOutputStream(NullOutputStream.NULL_OUTPUT_STREAM); entry.writeFileContent(cout); info.length = cout.getBytesWritten(); long newPos = pos + info.length; - if ((info.length % 2) != 0) + if ((info.length % 2) != 0) { newPos++; - if (newPos > MAX_FILE_SIZE) + } + if (newPos > MAX_FILE_SIZE) { throwRmpTooLarge(); + } rmpOutputFile.seek(newPos); entries.add(info); log.debug("Prepared data of entry " + entry + " bytes=" + info.length); @@ -128,19 +132,23 @@ public class RmpWriter { info.name = entry.getFileName(); info.extendsion = entry.getFileExtension(); int index = entries.indexOf(info); - if (index < 0) + if (index < 0) { throw new RuntimeException("Index for entry not found"); + } info = entries.get(index); rmpOutputFile.seek(info.offset); entry.writeFileContent(entryOut); - if (rmpOutputFile.getFilePointer() > MAX_FILE_SIZE) + if (rmpOutputFile.getFilePointer() > MAX_FILE_SIZE) { throwRmpTooLarge(); + } long newLength = rmpOutputFile.getFilePointer() - info.offset; - if (newLength != info.length) + if (newLength != info.length) { throw new RuntimeException("Length of entry has changed!"); - if ((newLength % 2) != 0) + } + if ((newLength % 2) != 0) { entryOut.write(0); + } // restore old file position rmpOutputFile.seek(pos); @@ -152,15 +160,16 @@ public class RmpWriter { /** * Writes the directory of the archive into the rmp file - * + * * @throws IOException * Error accessing disk */ public void writeDirectory() throws IOException { - if (projectedEntryCount != entries.size()) - throw new RuntimeException("Entry count does not correspond " - + "to the projected layer count: \nProjected: " + projectedEntryCount + "\nPresent:" - + entries.size()); + if (projectedEntryCount != entries.size()) { + throw new RuntimeException( + "Entry count does not correspond " + "to the projected layer count: \nProjected: " + + projectedEntryCount + "\nPresent:" + entries.size()); + } // Finalize the list of written entries RmpTools.writeFixedString(entryOut, "MAGELLAN", 8); @@ -229,24 +238,28 @@ public class RmpWriter { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } EntryInfo other = (EntryInfo) obj; if (extendsion == null) { - if (other.extendsion != null) + if (other.extendsion != null) { return false; - } else if (!extendsion.equals(other.extendsion)) + } + } else if (!extendsion.equals(other.extendsion)) { return false; + } if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - return true; + return other.name == null; + } else { + return name.equals(other.name); + } } } diff --git a/src/main/java/mobac/program/atlascreators/impl/rmp/TileContainer.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/TileContainer.java similarity index 87% rename from src/main/java/mobac/program/atlascreators/impl/rmp/TileContainer.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/rmp/TileContainer.java index 59f6a4e..dddbc12 100644 --- a/src/main/java/mobac/program/atlascreators/impl/rmp/TileContainer.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/TileContainer.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ /* ********************************************* * Copyright: Andreas Sander @@ -28,7 +28,6 @@ import java.util.ArrayList; /** * Container for tiles and link to subtrees - * */ public class TileContainer { @@ -47,28 +46,29 @@ public class TileContainer { } /** - * Set tile for given position. next is only valid if a previous value is - * set + * Set tile for given position. next is only valid if a previous value is set */ public void addTile(Tiledata tile, TileContainer next) { tiles.add(tile); - if (previous != null) + if (previous != null) { followUps.add(next); + } } /** - * Returns the number of tiles in this container including all sub - * containers + * Returns the number of tiles in this container including all sub containers */ public int getTileCount() { int count = tiles.size(); - if (previous != null) + if (previous != null) { count += previous.getTileCount(); + } - for (TileContainer next : followUps) + for (TileContainer next : followUps) { count += next.getTileCount(); + } return count; } @@ -93,8 +93,9 @@ public class TileContainer { writeContainer(os); /* --- And all subtrees --- */ - for (TileContainer tc : followUps) + for (TileContainer tc : followUps) { tc.writeTree(os); + } } else { /* --- Just write the tile itself, if it does not have subtrees --- */ writeContainer(os); @@ -134,17 +135,19 @@ public class TileContainer { } /* --- Offset to previous --- */ - if (previous == null) + if (previous == null) { RmpTools.writeValue(os, 0, 4); - else + } else { RmpTools.writeValue(os, 0x0f5c, 4); + } /* --- Offset to following --- */ for (int i = 0; i < 99; i++) { - if (i < followUps.size()) + if (i < followUps.size()) { RmpTools.writeValue(os, 0x0f5c + (i + 2) * 1992, 4); - else + } else { RmpTools.writeValue(os, 0, 4); + } } } } diff --git a/src/main/java/mobac/program/atlascreators/impl/rmp/Tiledata.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/Tiledata.java similarity index 91% rename from src/main/java/mobac/program/atlascreators/impl/rmp/Tiledata.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/rmp/Tiledata.java index de5e862..6ded89f 100644 --- a/src/main/java/mobac/program/atlascreators/impl/rmp/Tiledata.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/Tiledata.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ /* ********************************************* * Copyright: Andreas Sander @@ -22,17 +22,16 @@ package mobac.program.atlascreators.impl.rmp; +import mobac.exceptions.MapCreationException; +import mobac.program.interfaces.TileImageDataWriter; + import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; -import mobac.exceptions.MapCreationException; -import mobac.program.interfaces.TileImageDataWriter; - /** * Content of a single tile - * */ public class Tiledata { @@ -62,7 +61,8 @@ public class Tiledata { writer.processImage(image, bout); byte[] data = bout.toByteArray(); dataSize = data.length; - // Utilities.saveBytes(String.format("D:/jpg/mobac-%04d-%04d.jpg", posx, posy), data); + // Utilities.saveBytes(String.format("D:/jpg/mobac-%04d-%04d.jpg", posx, posy), + // data); RmpTools.writeValue(out, dataSize, 4); out.write(data); } catch (MapCreationException e) { diff --git a/src/main/java/mobac/program/atlascreators/impl/rmp/interfaces/RmpFileEntry.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/interfaces/RmpFileEntry.java similarity index 81% rename from src/main/java/mobac/program/atlascreators/impl/rmp/interfaces/RmpFileEntry.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/rmp/interfaces/RmpFileEntry.java index 9c41ea0..e7ee30f 100644 --- a/src/main/java/mobac/program/atlascreators/impl/rmp/interfaces/RmpFileEntry.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/interfaces/RmpFileEntry.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ /* ********************************************* * Copyright: Andreas Sander @@ -27,24 +27,23 @@ import java.io.OutputStream; /** * Interface for all files that are stored in a RMP file - * */ public interface RmpFileEntry { /** * Returns the content of the file as byte array - * + * * @throws InterruptedException */ - public void writeFileContent(OutputStream os) throws IOException, InterruptedException; + void writeFileContent(OutputStream os) throws IOException, InterruptedException; /** * Returns the name of the file without extension */ - public String getFileName(); + String getFileName(); /** * Returns the extension of the file */ - public String getFileExtension(); + String getFileExtension(); } diff --git a/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/Bmp2bit.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/Bmp2bit.java new file mode 100644 index 0000000..e3eeb67 --- /dev/null +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/Bmp2bit.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.atlascreators.impl.rmp.rmpfile; + +public class Bmp2bit extends GeneralRmpFileEntry { + private static final byte[] content = {73, 99, 111, 110, 32, 102, 105, 108, 101, 32, 118, 101, 114, 115, 105, 111, + 110, 32, 49, 46, 48, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 60, 0, 0, 0, -16, -1, -1, + 127, -40, 0, 0, 0, -15, -1, -1, 127, 116, 1, 0, 0, 0, 1, 0, 0, -1, -1, -1, -1, 88, 0, 0, 0, -104, 0, 0, 0, + 0, 0, 0, 0, 16, 0, 16, 0, 4, 2, 0, 0, 0, 0, 0, 0, 63, -1, -1, -4, 48, 0, 0, 12, 48, 0, 0, 12, 48, 0, 0, 12, + 48, 0, 0, 12, 48, 0, 0, 12, 48, 0, 0, 12, 48, 0, 0, 12, 48, 0, 0, 12, 48, 0, 0, 12, 48, 0, 0, 12, 48, 0, 0, + 12, 48, 0, 0, 12, 63, -1, -1, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1, -1, -64, 3, -1, -1, + -64, 3, -1, -1, -64, 3, -1, -1, -64, 3, -1, -1, -64, 3, -1, -1, -64, 3, -1, -1, -64, 3, -1, -1, -64, 3, -1, + -1, -64, 3, -1, -1, -64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -16, -1, -1, 127, -1, -1, -1, -1, -12, 0, 0, 0, + 52, 1, 0, 0, 0, 0, 0, 0, 1, 0, 64, 0, 4, 8, 0, 0, 81, -3, -40, -70, -124, 24, -99, -19, 46, -36, -3, -21, + -128, 98, 96, -75, 82, -99, 78, 108, -79, 18, -9, -36, -20, -88, -41, 84, -99, 88, 98, 40, 74, 93, 118, -31, + -73, -62, -98, -43, -41, 12, -75, 60, 69, 54, -54, -40, 51, -73, -18, 36, 83, 86, -8, 80, -2, 105, -61, + -122, 37, 114, 7, -7, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, + -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, + -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, -15, -1, -1, 127, -1, -1, -1, -1, -112, 1, 0, 0, -88, + 1, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0, 4, 8, 0, 0, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, + -1, -1, -1, -1, -1, 0, -1, -1}; + + public Bmp2bit() { + super(content, "bmp2bit", "ics"); + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + " " + getFileName() + "." + getFileExtension(); + } + +} diff --git a/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/Bmp4bit.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/Bmp4bit.java new file mode 100644 index 0000000..18cbffe --- /dev/null +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/Bmp4bit.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.atlascreators.impl.rmp.rmpfile; + +public class Bmp4bit extends GeneralRmpFileEntry { + private static final byte[] content = {73, 99, 111, 110, 32, 102, 105, 108, 101, 32, 118, 101, 114, 115, 105, 111, + 110, 32, 49, 46, 48, 46, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0, 0, 60, 0, 0, 0, -16, -1, -1, + 127, 88, 1, 0, 0, -15, -1, -1, 127, -12, 1, 0, 0, 0, 1, 0, 0, -1, -1, -1, -1, 88, 0, 0, 0, -40, 0, 0, 0, 0, + 0, 0, 0, 16, 0, 16, 0, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 51, 51, 51, 51, 51, 51, 48, 3, 0, 0, 0, 0, 0, + 0, 48, 3, 0, 0, 0, 0, 0, 0, 48, 3, 0, 0, 0, 0, 0, 0, 48, 3, 0, 0, 0, 0, 0, 0, 48, 3, 0, 0, 0, 0, 0, 0, 48, + 3, 0, 0, 0, 0, 0, 0, 48, 3, 0, 0, 0, 0, 0, 0, 48, 3, 0, 0, 0, 0, 0, 0, 48, 3, 0, 0, 0, 0, 0, 0, 48, 3, 0, 0, + 0, 0, 0, 0, 48, 3, 0, 0, 0, 0, 0, 0, 48, 3, 0, 0, 0, 0, 0, 0, 48, 3, 51, 51, 51, 51, 51, 51, 48, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, -1, -1, -1, -1, + -16, 0, 0, 15, -1, -1, -1, -1, -16, 0, 0, 15, -1, -1, -1, -1, -16, 0, 0, 15, -1, -1, -1, -1, -16, 0, 0, 15, + -1, -1, -1, -1, -16, 0, 0, 15, -1, -1, -1, -1, -16, 0, 0, 15, -1, -1, -1, -1, -16, 0, 0, 15, -1, -1, -1, -1, + -16, 0, 0, 15, -1, -1, -1, -1, -16, 0, 0, 15, -1, -1, -1, -1, -16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -16, -1, -1, 127, -1, -1, -1, -1, 116, 1, 0, 0, -76, 1, 0, 0, 0, 0, 0, 0, + 1, 0, 64, 0, 4, 8, 0, 0, 81, -3, -40, -70, -124, 24, -99, -19, 46, -36, -3, -21, -128, 98, 96, -75, 82, -99, + 78, 108, -79, 18, -9, -36, -20, -88, -41, 84, -99, 88, 98, 40, 74, 93, 118, -31, -73, -62, -98, -43, -41, + 12, -75, 60, 69, 54, -54, -40, 51, -73, -18, 36, 83, 86, -8, 80, -2, 105, -61, -122, 37, 114, 7, -7, 0, -1, + -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, + -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, + -1, -1, -1, -1, -1, 0, -15, -1, -1, 127, -1, -1, -1, -1, 16, 2, 0, 0, 40, 2, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0, + 4, 8, 0, 0, 49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, + 109, 110, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, 0, -1, -1}; + + public Bmp4bit() { + super(content, "bmp4bit", "ics"); + } + + @Override + public String toString() { + return this.getClass().getSimpleName() + " " + getFileName() + "." + getFileExtension(); + } + +} diff --git a/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/GeneralRmpFileEntry.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/GeneralRmpFileEntry.java similarity index 90% rename from src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/GeneralRmpFileEntry.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/GeneralRmpFileEntry.java index 21bd3b6..97b9eb4 100644 --- a/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/GeneralRmpFileEntry.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/GeneralRmpFileEntry.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ /* ********************************************* * Copyright: Andreas Sander @@ -22,15 +22,13 @@ package mobac.program.atlascreators.impl.rmp.rmpfile; +import mobac.program.atlascreators.impl.rmp.interfaces.RmpFileEntry; + import java.io.IOException; import java.io.OutputStream; -import mobac.program.atlascreators.impl.rmp.interfaces.RmpFileEntry; - - /** * General class for storing the content of a rmp file - * */ public class GeneralRmpFileEntry implements RmpFileEntry { protected final byte[] content; @@ -57,7 +55,6 @@ public class GeneralRmpFileEntry implements RmpFileEntry { @Override public String toString() { - return "GeneralRmpFileEntry \"" + filename + "." + extension + "\" content-len=" - + content.length; + return "GeneralRmpFileEntry \"" + filename + "." + extension + "\" content-len=" + content.length; } } diff --git a/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/RmpIni.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/RmpIni.java similarity index 86% rename from src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/RmpIni.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/RmpIni.java index c2f1a70..eb3cb30 100644 --- a/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/RmpIni.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rmp/rmpfile/RmpIni.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ /* ********************************************* * Copyright: Andreas Sander @@ -22,23 +22,21 @@ package mobac.program.atlascreators.impl.rmp.rmpfile; +import mobac.program.atlascreators.impl.rmp.RmpTools; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.ByteArrayOutputStream; import java.io.PrintStream; -import mobac.program.atlascreators.impl.rmp.RmpTools; - -import org.apache.log4j.Logger; - - /** * Instance of the rmp.ini file - * + * * @author Andreas - * */ public class RmpIni extends GeneralRmpFileEntry { - private static final Logger log = Logger.getLogger(RmpIni.class); + private static final Logger log = LoggerFactory.getLogger(RmpIni.class); public RmpIni(String layername, int count) { super(generateContent(layername, count), "rmp", "ini"); diff --git a/src/main/java/mobac/program/atlascreators/impl/rungps/RunGPSAtlasFile.java b/mobac/src/main/java/mobac/program/atlascreators/impl/rungps/RunGPSAtlasFile.java similarity index 90% rename from src/main/java/mobac/program/atlascreators/impl/rungps/RunGPSAtlasFile.java rename to mobac/src/main/java/mobac/program/atlascreators/impl/rungps/RunGPSAtlasFile.java index 934ceb5..266a217 100644 --- a/src/main/java/mobac/program/atlascreators/impl/rungps/RunGPSAtlasFile.java +++ b/mobac/src/main/java/mobac/program/atlascreators/impl/rungps/RunGPSAtlasFile.java @@ -1,21 +1,23 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.impl.rungps; +import mobac.utilities.Utilities; + import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; @@ -23,14 +25,11 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.RandomAccessFile; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; -import mobac.utilities.Charsets; -import mobac.utilities.Utilities; - /** - * * @author Tom Henne, eSymetric */ public class RunGPSAtlasFile { @@ -44,8 +43,211 @@ public class RunGPSAtlasFile { int offset = 0; int indexLength = 0; + public RunGPSAtlasFile(String filePath, boolean write) throws IOException { + + this.offset = RunGPSAtlasHeader.HEADER_SIZE; + + if (write) { + cacheFile = new File(filePath + ".cac"); + cacheOutStream = new BufferedOutputStream(new FileOutputStream(cacheFile), 8216); + + raf = new RandomAccessFile(filePath, "rw"); + raf.setLength(0); // delete existing content + + indexLength = offset; + RAINode root = new RAINode(); + root.writeNew(); + } else { + raf = new RandomAccessFile(filePath, "r"); + rah.readHeader(); + } + } + + public static List makeHierarchyFromPath(String path) { + // e.g. /10/3487/8345.png + + // sure that replace() is correct? may be replaceAll() would be better? + path = path.replace(File.separatorChar, '/'); + + int p = path.indexOf('.'); + if (p > 0) { + path = path.substring(0, p); // remove suffix + } + if (path.startsWith("/")) { + path = path.substring(1); + } + + try { + List hierarchy = new ArrayList(); + for (;;) { + p = path.indexOf('/'); + if (p > 0) { + hierarchy.add(Integer.parseInt(path.substring(0, p))); + path = path.substring(p + 1); + } else { + hierarchy.add(Integer.parseInt(path)); + break; + } + } + + return hierarchy; + } catch (NumberFormatException e) { + return null; + } + + } + + public boolean readSuccess() { + return rah.readSuccess(); + } + + public RAINode getRootNode() throws IOException { + RAINode root = new RAINode(); + root.readFrom(offset); + return root; + } + + public String listAll() throws IOException { + return getRootNode().listAll(); + } + + public void close() throws IOException { + if (cacheOutStream != null) { + cacheOutStream.close(); + } + if (raf != null) { + raf.close(); + } + } + + public void finishArchive() throws IOException { + cacheOutStream.close(); + cacheOutStream = null; + + FileInputStream fis = new FileInputStream(cacheFile); + + rah.indexSize = indexLength - RunGPSAtlasHeader.HEADER_SIZE; + rah.writeHeader(); + + byte[] buf = new byte[4096]; + + raf.seek(indexLength); + for (;;) { + int l = fis.read(buf); + if (l <= 0) { + break; + + } + raf.write(buf, 0, l); + } + + fis.close(); + + Utilities.deleteFile(cacheFile); + close(); + } + + public void addData(List hierarchy, byte[] data) throws IOException { + addData(hierarchy, data, data.length); + } + + public void addData(List hierarchy, byte[] data, int length) throws IOException { + cacheOutStream.write(data, 0, length); + + List posHierarchy = new ArrayList<>(hierarchy); + posHierarchy.add(1); // position + setValue(posHierarchy, positionInCacheFile); + + List lenHierarchy = new ArrayList<>(hierarchy); + lenHierarchy.add(2); // size + setValue(lenHierarchy, length); + + positionInCacheFile += length; + + } + + public byte[] getData(String path) throws IOException { + return getData(makeHierarchyFromPath(path)); + } + + public byte[] getData(List keyHierarchy) throws IOException { + ArrayList posHierarchy = new ArrayList<>(keyHierarchy); + posHierarchy.add(1); // position + long indexPosition = getValue(posHierarchy); + if (indexPosition == -1) { + return null; + } + ArrayList sizeHierarchy = new ArrayList<>(keyHierarchy); + sizeHierarchy.add(2); // size + int size = (int) getValue(sizeHierarchy); + if (size == -1) { + return null; + } + + byte[] buf = new byte[size]; + raf.seek(RunGPSAtlasHeader.HEADER_SIZE + rah.indexSize + indexPosition); + raf.readFully(buf); + return buf; + } + + public void setValue(List keyHierarchy, long value) throws IOException { + setValueImpl(getRootNode(), keyHierarchy, value); + } + + public void setValue(String path, long value) throws IOException { + setValue(makeHierarchyFromPath(path), value); + } + + private void setValueImpl(RAINode currentNode, List keyHierarchy, long value) throws IOException { + int key = keyHierarchy.get(0); + keyHierarchy.remove(0); + RAINode n = currentNode.getChildNode(key, true); + if (keyHierarchy.isEmpty()) { + n.value = value; + n.write(); + } else { + setValueImpl(n, keyHierarchy, value); + } + } + + public long getValue(List keyHierarchy) throws IOException { + RAINode n = getRootNode().getChildNode(keyHierarchy); + return n == null ? -1L : n.value; + } + + public long getValue(String path) throws IOException { + return getValue(makeHierarchyFromPath(path)); + } + + public void setString(List keyHierarchy, String value) throws IOException { + byte[] data = value.getBytes(StandardCharsets.UTF_8); + addData(keyHierarchy, data); + } + + public void setString(String path, String value) throws IOException { + setString(makeHierarchyFromPath(path), value); + } + + public String getString(List keyHierarchy) throws IOException { + byte[] data = getData(keyHierarchy); + if (data != null) { + return new String(data, StandardCharsets.UTF_8); + } + return null; + } + + public String getString(String path) throws IOException { + return getString(makeHierarchyFromPath(path)); + } + public class RAINode { + int key; + long value; + int next; + int child; + int index; + RAINode() { key = -1; value = -1L; @@ -54,12 +256,6 @@ public class RunGPSAtlasFile { index = -1; } - int key; - long value; - int next; - int child; - int index; - void readFrom(int index) throws IOException { this.index = index; raf.seek(index); @@ -197,10 +393,6 @@ public class RunGPSAtlasFile { } } - public boolean readSuccess() { - return rah.readSuccess(); - } - public class RunGPSAtlasHeader { public final static long FILETYPE_KEY = 8723487877262773L; @@ -234,201 +426,4 @@ public class RunGPSAtlasFile { } } - public RunGPSAtlasFile(String filePath, boolean write) throws IOException { - - this.offset = RunGPSAtlasHeader.HEADER_SIZE; - - if (write) { - cacheFile = new File(filePath + ".cac"); - cacheOutStream = new BufferedOutputStream(new FileOutputStream(cacheFile), 8216); - - raf = new RandomAccessFile(filePath, "rw"); - raf.setLength(0); // delete existing content - - indexLength = offset; - RAINode root = new RAINode(); - root.writeNew(); - } else { - raf = new RandomAccessFile(filePath, "r"); - rah.readHeader(); - } - } - - public RAINode getRootNode() throws IOException { - RAINode root = new RAINode(); - root.readFrom(offset); - return root; - } - - public String listAll() throws IOException { - return getRootNode().listAll(); - } - - public void close() throws IOException { - if (cacheOutStream != null) { - cacheOutStream.close(); - } - if (raf != null) { - raf.close(); - } - } - - public void finishArchive() throws IOException { - cacheOutStream.close(); - cacheOutStream = null; - - FileInputStream fis = new FileInputStream(cacheFile); - - rah.indexSize = indexLength - RunGPSAtlasHeader.HEADER_SIZE; - rah.writeHeader(); - - byte[] buf = new byte[4096]; - - raf.seek(indexLength); - for (;;) { - int l = fis.read(buf); - if (l <= 0) { - break; - - } - raf.write(buf, 0, l); - } - - fis.close(); - - Utilities.deleteFile(cacheFile); - close(); - } - - public void addData(List hierarchy, byte[] data) throws IOException { - addData(hierarchy, data, data.length); - } - - public void addData(List hierarchy, byte[] data, int length) throws IOException { - cacheOutStream.write(data, 0, length); - - List posHierarchy = new ArrayList(); - posHierarchy.addAll(hierarchy); - posHierarchy.add(1); // position - setValue(posHierarchy, positionInCacheFile); - - List lenHierarchy = new ArrayList(); - lenHierarchy.addAll(hierarchy); - lenHierarchy.add(2); // size - setValue(lenHierarchy, length); - - positionInCacheFile += length; - - } - - public static List makeHierarchyFromPath(String path) { - // e.g. /10/3487/8345.png - - // sure that replace() is correct? may be replaceAll() would be better? - path = path.replace(File.separatorChar, '/'); - - int p = path.indexOf('.'); - if (p > 0) { - path = path.substring(0, p); // remove suffix - } - if (path.startsWith("/")) { - path = path.substring(1); - } - - try { - List hierarchy = new ArrayList(); - for (;;) { - p = path.indexOf('/'); - if (p > 0) { - hierarchy.add(Integer.parseInt(path.substring(0, p))); - path = path.substring(p + 1); - } else { - hierarchy.add(Integer.parseInt(path)); - break; - } - } - - return hierarchy; - } catch (NumberFormatException e) { - return null; - } - - } - - public byte[] getData(String path) throws IOException { - return getData(makeHierarchyFromPath(path)); - } - - public byte[] getData(List keyHierarchy) throws IOException { - ArrayList posHierarchy = new ArrayList(); - posHierarchy.addAll(keyHierarchy); - posHierarchy.add(1); // position - long indexPosition = getValue(posHierarchy); - if (indexPosition == -1) { - return null; - } - ArrayList sizeHierarchy = new ArrayList(); - sizeHierarchy.addAll(keyHierarchy); - sizeHierarchy.add(2); // size - int size = (int) getValue(sizeHierarchy); - if (size == -1) { - return null; - } - - byte[] buf = new byte[size]; - raf.seek(RunGPSAtlasHeader.HEADER_SIZE + rah.indexSize + indexPosition); - raf.readFully(buf); - return buf; - } - - public void setValue(List keyHierarchy, long value) throws IOException { - setValueImpl(getRootNode(), keyHierarchy, value); - } - - public void setValue(String path, long value) throws IOException { - setValue(makeHierarchyFromPath(path), value); - } - - private void setValueImpl(RAINode currentNode, List keyHierarchy, long value) throws IOException { - int key = keyHierarchy.get(0); - keyHierarchy.remove(0); - RAINode n = currentNode.getChildNode(key, true); - if (keyHierarchy.isEmpty()) { - n.value = value; - n.write(); - } else { - setValueImpl(n, keyHierarchy, value); - } - } - - public long getValue(List keyHierarchy) throws IOException { - RAINode n = getRootNode().getChildNode(keyHierarchy); - return n == null ? -1L : n.value; - } - - public long getValue(String path) throws IOException { - return getValue(makeHierarchyFromPath(path)); - } - - public void setString(List keyHierarchy, String value) throws IOException { - byte[] data = value.getBytes(Charsets.UTF_8); - addData(keyHierarchy, data); - } - - public void setString(String path, String value) throws IOException { - setString(makeHierarchyFromPath(path), value); - } - - public String getString(List keyHierarchy) throws IOException { - byte[] data = getData(keyHierarchy); - if (data != null) { - return new String(data, Charsets.UTF_8); - } - return null; - } - - public String getString(String path) throws IOException { - return getString(makeHierarchyFromPath(path)); - } - } diff --git a/src/main/java/mobac/program/atlascreators/tileprovider/CacheTileProvider.java b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/CacheTileProvider.java similarity index 76% rename from src/main/java/mobac/program/atlascreators/tileprovider/CacheTileProvider.java rename to mobac/src/main/java/mobac/program/atlascreators/tileprovider/CacheTileProvider.java index 0879264..93c1fa4 100644 --- a/src/main/java/mobac/program/atlascreators/tileprovider/CacheTileProvider.java +++ b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/CacheTileProvider.java @@ -1,53 +1,49 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.tileprovider; +import mobac.program.interfaces.MapSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.image.BufferedImage; import java.io.IOException; import java.lang.ref.SoftReference; -import java.util.Hashtable; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.LinkedBlockingQueue; -import mobac.program.interfaces.MapSource; - -import org.apache.log4j.Logger; - /** - * A tile cache with speculative loading on a separate thread. Usually this decreases map generation time on multi-core - * systems. + * A tile cache with speculative loading on a separate thread. Usually this + * decreases map generation time on multi-core systems. */ -public class CacheTileProvider implements TileProvider { - - private Logger log = Logger.getLogger(CacheTileProvider.class); +public class CacheTileProvider implements TileProvider, AutoCloseable { /** * Counter for identifying the different threads */ private static int PRELOADER_THREAD_NUM = 1; - - private Hashtable cache; - - private PreLoadThread preLoader = new PreLoadThread(); - protected final TileProvider tileProvider; + private final Logger log = LoggerFactory.getLogger(CacheTileProvider.class); + private final Map cache = new ConcurrentHashMap<>(500); + private PreLoadThread preLoader = new PreLoadThread(); public CacheTileProvider(TileProvider tileProvider) { this.tileProvider = tileProvider; - cache = new Hashtable(500); preLoader.start(); } @@ -61,8 +57,9 @@ public class CacheTileProvider implements TileProvider { if (cachedTile != null) { CachedTile tile = cachedTile.get(); if (tile != null) { - if (tile.loaded) - log.trace(String.format("Cache hit: x=%d y=%d", x, y)); + if (tile.loaded) { + log.trace("Cache hit: x={} y={}", x, y); + } image = tile.getImage(); if (!tile.nextLoadJobCreated) { // log.debug(String.format("Preload job added : x=%d y=%d l=%d", @@ -73,7 +70,7 @@ public class CacheTileProvider implements TileProvider { } } if (image == null) { - log.trace(String.format("Cache miss: x=%d y=%d", x, y)); + log.trace("Cache miss: x={}} y={}}", x, y); // log.debug(String.format("Preload job added : x=%d y=%d l=%d", x + // 1, y, layer)); preloadTile(new CachedTile(new CacheKey(x + 1, y))); @@ -88,11 +85,11 @@ public class CacheTileProvider implements TileProvider { } } - public byte[] getTileData(int layer, int x, int y) throws IOException { + public byte[] getTileData(int layer, int x, int y) { throw new RuntimeException("Not implemented"); } - public byte[] getTileData(int x, int y) throws IOException { + public byte[] getTileData(int x, int y) { throw new RuntimeException("Not implemented"); } @@ -103,17 +100,18 @@ public class CacheTileProvider implements TileProvider { private void preloadTile(CachedTile tile) { if (preLoader.queue.remainingCapacity() < 1) { // Preloader thread is too slow - log.trace("Preloading rejected: " + tile.key); + log.trace("Preloading rejected: {}", tile.key); return; } - if (cache.get(tile.key) != null) + if (cache.get(tile.key) != null) { return; + } try { preLoader.queue.add(tile); cache.put(tile.key, new SRCachedTile(tile)); } catch (IllegalStateException e) { // Queue is "full" - log.trace("Preloading rejected: " + tile.key); + log.trace("Preloading rejected: {}", tile.key); } } @@ -130,9 +128,8 @@ public class CacheTileProvider implements TileProvider { } @Override - protected void finalize() throws Throwable { + public void close() { cleanup(); - super.finalize(); } private static class SRCachedTile extends SoftReference { @@ -143,35 +140,6 @@ public class CacheTileProvider implements TileProvider { } - private class PreLoadThread extends Thread { - - private LinkedBlockingQueue queue = null; - - public PreLoadThread() { - super("ImagePreLoadThread" + (PRELOADER_THREAD_NUM++)); - log.debug("Image pre-loader thread started"); - // pre-loading more than 20 tiles doesn't make much sense - queue = new LinkedBlockingQueue(20); - } - - @Override - public void run() { - CachedTile tile; - try { - while (true) { - tile = queue.take(); - if (tile != null && !tile.loaded) { - // log.trace("Loading image async: " + tile); - tile.loadImage(); - } - } - } catch (InterruptedException e) { - log.debug("Image pre-loader thread terminated"); - } - } - - } - private static class CacheKey { int x; int y; @@ -193,18 +161,20 @@ public class CacheTileProvider implements TileProvider { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } CacheKey other = (CacheKey) obj; - if (x != other.x) + if (x != other.x) { return false; - if (y != other.y) - return false; - return true; + } + return y == other.y; } @Override @@ -214,13 +184,44 @@ public class CacheTileProvider implements TileProvider { } + private class PreLoadThread extends Thread { + + /** + * pre-loading more than 20 tiles doesn't make much sense + */ + private final LinkedBlockingQueue queue = new LinkedBlockingQueue<>(20); + + public PreLoadThread() { + super("ImagePreLoadThread" + (PRELOADER_THREAD_NUM++)); + setDaemon(true); + } + + @Override + public void run() { + log.debug("Image pre-loader thread started"); + CachedTile tile; + try { + while (true) { + tile = queue.take(); + if (tile != null && !tile.loaded) { + // log.trace("Loading image async: " + tile); + tile.loadImage(); + } + } + } catch (InterruptedException e) { + log.debug("Image pre-loader thread terminated"); + } + } + + } + private class CachedTile { - CacheKey key; - private BufferedImage image; - private IOException loadException = null; + final CacheKey key; boolean loaded = false; boolean nextLoadJobCreated = false; + private BufferedImage image; + private IOException loadException = null; public CachedTile(CacheKey key) { super(); @@ -240,10 +241,12 @@ public class CacheTileProvider implements TileProvider { } public synchronized BufferedImage getImage() throws IOException { - if (!loaded) + if (!loaded) { loadImage(); - if (loadException != null) + } + if (loadException != null) { throw loadException; + } return image; } diff --git a/src/main/java/mobac/program/atlascreators/tileprovider/ConvertedRawTileProvider.java b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/ConvertedRawTileProvider.java similarity index 79% rename from src/main/java/mobac/program/atlascreators/tileprovider/ConvertedRawTileProvider.java rename to mobac/src/main/java/mobac/program/atlascreators/tileprovider/ConvertedRawTileProvider.java index 8c97366..f0c28b3 100644 --- a/src/main/java/mobac/program/atlascreators/tileprovider/ConvertedRawTileProvider.java +++ b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/ConvertedRawTileProvider.java @@ -1,49 +1,49 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.tileprovider; -import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import javax.imageio.ImageIO; - import mobac.program.interfaces.TileImageDataWriter; import mobac.program.model.TileImageFormat; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + /** - * Loads a tile from the underlying {@link TileProvider}, loads the tile to memory, converts it to the desired - * {@link TileImageFormat} and returns the binary representation of the image in the specified format. + * Loads a tile from the underlying {@link TileProvider}, loads the tile to + * memory, converts it to the desired {@link TileImageFormat} and returns the + * binary representation of the image in the specified format. */ public class ConvertedRawTileProvider extends FilterTileProvider { - private TileImageDataWriter writer; + private final TileImageDataWriter writer; public ConvertedRawTileProvider(TileProvider tileProvider, TileImageFormat tileImageFormat) { super(tileProvider); - writer = tileImageFormat.getDataWriter(); - writer.initialize(); + writer = tileImageFormat.getDataWriterBuilder().build(); ImageIO.setUseCache(false); } public byte[] getTileData(int x, int y) throws IOException { BufferedImage image = getTileImage(x, y); - if (image == null) + if (image == null) { return null; + } ByteArrayOutputStream buffer = new ByteArrayOutputStream(32000); writer.processImage(image, buffer); return buffer.toByteArray(); diff --git a/src/main/java/mobac/program/atlascreators/tileprovider/DownloadedTileProvider.java b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/DownloadedTileProvider.java similarity index 78% rename from src/main/java/mobac/program/atlascreators/tileprovider/DownloadedTileProvider.java rename to mobac/src/main/java/mobac/program/atlascreators/tileprovider/DownloadedTileProvider.java index 2394d8c..b764451 100644 --- a/src/main/java/mobac/program/atlascreators/tileprovider/DownloadedTileProvider.java +++ b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/DownloadedTileProvider.java @@ -1,40 +1,37 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.tileprovider; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.IOException; - -import javax.imageio.ImageIO; - import mobac.program.interfaces.MapInterface; import mobac.program.interfaces.MapSource; import mobac.program.model.TileImageType; import mobac.utilities.tar.TarIndex; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Logger; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.IOException; public class DownloadedTileProvider implements TileProvider { - private static final Logger log = Logger.getLogger(DownloadedTileProvider.class); - public static final String TILE_FILENAME_PATTERN = "x%dy%d"; - + private static final Logger log = LoggerFactory.getLogger(DownloadedTileProvider.class); protected final TarIndex tarIndex; protected final MapInterface map; protected final TileImageType mapTileType; @@ -52,9 +49,14 @@ public class DownloadedTileProvider implements TileProvider { public BufferedImage getTileImage(int x, int y) throws IOException { byte[] unconvertedTileData = getTileData(x, y); - if (unconvertedTileData == null) + if (unconvertedTileData == null) { return null; - return ImageIO.read(new ByteArrayInputStream(unconvertedTileData)); + } + try { + return ImageIO.read(new ByteArrayInputStream(unconvertedTileData)); + } catch (Exception e) { + throw new IOException("Unable to load image x=" + x + " y=" + y + " - error: " + e); + } } public boolean preferTileImageUsage() { diff --git a/src/main/java/mobac/program/atlascreators/tileprovider/FilterTileProvider.java b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/FilterTileProvider.java similarity index 81% rename from src/main/java/mobac/program/atlascreators/tileprovider/FilterTileProvider.java rename to mobac/src/main/java/mobac/program/atlascreators/tileprovider/FilterTileProvider.java index 120d4f0..7e902cb 100644 --- a/src/main/java/mobac/program/atlascreators/tileprovider/FilterTileProvider.java +++ b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/FilterTileProvider.java @@ -1,31 +1,32 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.tileprovider; +import mobac.program.interfaces.MapSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.awt.image.BufferedImage; import java.io.IOException; -import mobac.program.interfaces.MapSource; - -import org.apache.log4j.Logger; - /** - * Base implementation of an {@link TileProvider} that changes somehow the images, e.g. combines two layers to one or - * paints something onto a tile image. + * Base implementation of an {@link TileProvider} that changes somehow the + * images, e.g. combines two layers to one or paints something onto a tile + * image. */ public abstract class FilterTileProvider implements TileProvider { @@ -34,7 +35,7 @@ public abstract class FilterTileProvider implements TileProvider { protected final TileProvider tileProvider; public FilterTileProvider(TileProvider tileProvider) { - log = Logger.getLogger(this.getClass()); + log = LoggerFactory.getLogger(this.getClass()); this.tileProvider = tileProvider; } diff --git a/src/main/java/mobac/program/atlascreators/tileprovider/FilteredMapSourceProvider.java b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/FilteredMapSourceProvider.java similarity index 75% rename from src/main/java/mobac/program/atlascreators/tileprovider/FilteredMapSourceProvider.java rename to mobac/src/main/java/mobac/program/atlascreators/tileprovider/FilteredMapSourceProvider.java index 9babcfd..53dd2a2 100644 --- a/src/main/java/mobac/program/atlascreators/tileprovider/FilteredMapSourceProvider.java +++ b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/FilteredMapSourceProvider.java @@ -1,36 +1,37 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.tileprovider; -import java.awt.image.BufferedImage; -import java.io.IOException; - import mobac.program.interfaces.MapInterface; import mobac.program.interfaces.MapSource; import mobac.program.interfaces.MapSource.LoadMethod; import mobac.program.interfaces.TileFilter; +import java.awt.image.BufferedImage; +import java.io.IOException; + /** - * Based on a given {@link TileFilter} implementation an {@link FilteredMapSourceProvider} instance ignores certain - * requests via {@link #getTileData(int, int)} and {@link #getTileImage(int, int)} and returns null - * instead. - * - * This functionality is required especially for polygonal maps where certain tiles which are located outside of the - * polygon should be ignored. + * Based on a given {@link TileFilter} implementation an + * {@link FilteredMapSourceProvider} instance ignores certain requests via + * {@link #getTileData(int, int)} and {@link #getTileImage(int, int)} and + * returns null instead. + *

      + * This functionality is required especially for polygonal maps where certain + * tiles which are located outside of the polygon should be ignored. */ public class FilteredMapSourceProvider extends MapSourceProvider { @@ -47,15 +48,17 @@ public class FilteredMapSourceProvider extends MapSourceProvider { @Override public byte[] getTileData(int x, int y) throws IOException { - if (!tileFilter.testTile(x, y, zoom, mapSource)) + if (!tileFilter.testTile(x, y, zoom, mapSource)) { return null; + } return super.getTileData(x, y); } @Override public BufferedImage getTileImage(int x, int y) throws IOException { - if (!tileFilter.testTile(x, y, zoom, mapSource)) + if (!tileFilter.testTile(x, y, zoom, mapSource)) { return null; + } return super.getTileImage(x, y); } diff --git a/mobac/src/main/java/mobac/program/atlascreators/tileprovider/GpxPainterTileProvider.java b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/GpxPainterTileProvider.java new file mode 100644 index 0000000..0511c25 --- /dev/null +++ b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/GpxPainterTileProvider.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.atlascreators.tileprovider; + +import mobac.data.gpx.gpx11.Gpx; +import mobac.data.gpx.gpx11.TrkType; +import mobac.data.gpx.gpx11.TrksegType; +import mobac.data.gpx.gpx11.WptType; +import mobac.data.gpx.interfaces.GpxPoint; +import mobac.program.interfaces.MapSource; +import mobac.program.interfaces.MapSpace; +import mobac.program.model.TileImageFormat; + +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Incomplete! + *

      + * TODO: Fully implement this class so that the content (points, tracks, ...) + * can be painted on each tile. If the implementation is complete the + * {@link GpxPainterTileProvider} can be chained into the tile provider chain + * after the {@link DownloadedTileProvider} (see AtlasThread line ~348). + *

      + * Problem: texts and lines that span multiple tiles. + */ +public class GpxPainterTileProvider extends ConvertedRawTileProvider { + + private final MapSpace mapSpace; + private final int zoom; + + private final List points = new ArrayList<>(); + private final List lines = new ArrayList<>(); + + public GpxPainterTileProvider(MapSourceProvider tileProvider, TileImageFormat tileImageFormat, Gpx gpx) { + super(tileProvider, tileImageFormat); + zoom = tileProvider.getZoom(); + MapSource mapSource = tileProvider.getMapSource(); + mapSpace = mapSource.getMapSpace(); + + // TODO Prepare GPX points + for (TrkType trk : gpx.getTrk()) { + for (TrksegType trkSeg : trk.getTrkseg()) { + List trackPoints = trkSeg.getTrkpt(); + + if (trackPoints.size() < 2) { + continue; + } + Point last = convert(trackPoints.get(0)); + points.add(last); + for (int i = 1; i < trackPoints.size(); i++) { + Point current = convert(trackPoints.get(i)); + points.add(current); + lines.add(new Line(last, current)); + last = current; + } + } + } + } + + private Point convert(GpxPoint gpxPoint) { + int x = mapSpace.cLonToX(gpxPoint.getLon().doubleValue(), zoom); + int y = mapSpace.cLatToY(gpxPoint.getLat().doubleValue(), zoom); + return new Point(x, y); + } + + @Override + public BufferedImage getTileImage(int x, int y) throws IOException { + BufferedImage image = super.getTileImage(x, y); + + // Calculate tile bounds: + final int tileSize = mapSpace.getTileSize(); + int xMin = tileSize * x; + int yMin = tileSize * y; + int xMax = xMin + tileSize - 1; + int yMax = yMin + tileSize - 1; + + Graphics2D g = (Graphics2D) image.getGraphics(); + try { + for (Point p : points) { + if (p.x < xMin || p.x > xMax || p.y < yMin || p.y > yMax) { + continue; // Point is outside of tile + } + int px = p.x - xMin; + int py = p.y - yMin; + g.drawOval(px, py, 5, 5); + } + // TODO paint lines + } finally { + g.dispose(); + } + + return image; + } + + public static class Line { + public final Point start; + public final Point end; + + public Line(Point start, Point end) { + super(); + this.start = start; + this.end = end; + } + + } +} diff --git a/src/main/java/mobac/program/atlascreators/tileprovider/MapSourceProvider.java b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/MapSourceProvider.java similarity index 88% rename from src/main/java/mobac/program/atlascreators/tileprovider/MapSourceProvider.java rename to mobac/src/main/java/mobac/program/atlascreators/tileprovider/MapSourceProvider.java index 0bdbf8c..58eee01 100644 --- a/src/main/java/mobac/program/atlascreators/tileprovider/MapSourceProvider.java +++ b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/MapSourceProvider.java @@ -1,30 +1,31 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.tileprovider; -import java.awt.image.BufferedImage; -import java.io.IOException; - import mobac.exceptions.TileException; import mobac.program.interfaces.MapSource; import mobac.program.interfaces.MapSource.LoadMethod; +import java.awt.image.BufferedImage; +import java.io.IOException; + /** - * A {@link TileProvider} implementation that retrieves all tiles directly from the {@link MapSource}. + * A {@link TileProvider} implementation that retrieves all tiles directly from + * the {@link MapSource}. */ public class MapSourceProvider implements TileProvider { @@ -33,12 +34,11 @@ public class MapSourceProvider implements TileProvider { protected final LoadMethod loadMethod; /** - * * @param mapSource * @param zoom * @param loadMethod - * defines if the tile should be taken from tile cache or from it's original source (web server, - * generated...). + * defines if the tile should be taken from tile cache or from it's + * original source (web server, generated...). */ public MapSourceProvider(MapSource mapSource, int zoom, LoadMethod loadMethod) { super(); diff --git a/src/main/java/mobac/program/atlascreators/tileprovider/PngTileProvider.java b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/PngTileProvider.java similarity index 81% rename from src/main/java/mobac/program/atlascreators/tileprovider/PngTileProvider.java rename to mobac/src/main/java/mobac/program/atlascreators/tileprovider/PngTileProvider.java index 797975e..7da9695 100644 --- a/src/main/java/mobac/program/atlascreators/tileprovider/PngTileProvider.java +++ b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/PngTileProvider.java @@ -1,54 +1,55 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.tileprovider; +import mobac.program.model.TileImageType; +import mobac.program.tiledatawriter.TileImagePngDataWriter; +import mobac.utilities.imageio.ImageFormatDetector; + import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; -import mobac.program.interfaces.TileImageDataWriter; -import mobac.program.model.TileImageType; -import mobac.program.tiledatawriter.TileImagePngDataWriter; -import mobac.utilities.Utilities; - /** - * A tile provider for atlas formats that only allow PNG images. Each image processed is checked + * A tile provider for atlas formats that only allow PNG images. Each image + * processed is checked */ public class PngTileProvider extends FilterTileProvider { - final TileImageDataWriter writer; + final TileImagePngDataWriter writer; public PngTileProvider(TileProvider tileProvider) { super(tileProvider); writer = new TileImagePngDataWriter(); - writer.initialize(); } @Override public byte[] getTileData(int x, int y) throws IOException { if (!tileProvider.preferTileImageUsage()) { byte[] data = super.getTileData(x, y); - if (Utilities.getImageType(data) == TileImageType.PNG) + if (ImageFormatDetector.getImageType(data) == TileImageType.PNG) { return data; + } } ByteArrayOutputStream buffer = new ByteArrayOutputStream(32000); BufferedImage image = getTileImage(x, y); - if (image == null) + if (image == null) { return null; + } writer.processImage(image, buffer); return buffer.toByteArray(); } diff --git a/src/main/java/mobac/program/atlascreators/tileprovider/TileProvider.java b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/TileProvider.java similarity index 71% rename from src/main/java/mobac/program/atlascreators/tileprovider/TileProvider.java rename to mobac/src/main/java/mobac/program/atlascreators/tileprovider/TileProvider.java index ce979da..06e0826 100644 --- a/src/main/java/mobac/program/atlascreators/tileprovider/TileProvider.java +++ b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/TileProvider.java @@ -1,39 +1,39 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.tileprovider; +import mobac.program.interfaces.MapSource; + import java.awt.image.BufferedImage; import java.io.IOException; -import mobac.program.interfaces.MapSource; - public interface TileProvider { - public byte[] getTileData(int x, int y) throws IOException; + byte[] getTileData(int x, int y) throws IOException; - public BufferedImage getTileImage(int x, int y) throws IOException; + BufferedImage getTileImage(int x, int y) throws IOException; - public MapSource getMapSource(); + MapSource getMapSource(); /** - * Indicates if subsequent filter in the filter-chain should prefer the {@link #getTileImage(int, int)} or - * {@link #getTileData(int, int)} method. - * + * Indicates if subsequent filter in the filter-chain should prefer the + * {@link #getTileImage(int, int)} or {@link #getTileData(int, int)} method. + * * @return */ - public boolean preferTileImageUsage(); + boolean preferTileImageUsage(); } diff --git a/src/main/java/mobac/program/atlascreators/tileprovider/TileStoreTileProvider.java b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/TileStoreTileProvider.java similarity index 86% rename from src/main/java/mobac/program/atlascreators/tileprovider/TileStoreTileProvider.java rename to mobac/src/main/java/mobac/program/atlascreators/tileprovider/TileStoreTileProvider.java index c8676ea..7b1797c 100644 --- a/src/main/java/mobac/program/atlascreators/tileprovider/TileStoreTileProvider.java +++ b/mobac/src/main/java/mobac/program/atlascreators/tileprovider/TileStoreTileProvider.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.atlascreators.tileprovider; @@ -20,8 +20,8 @@ import mobac.program.interfaces.MapSource; import mobac.program.interfaces.MapSource.LoadMethod; /** - * A {@link TileProvider} implementation that retrieves all tiles from the tile store (if the mapSource - * supports that). + * A {@link TileProvider} implementation that retrieves all tiles from the tile + * store (if the mapSource supports that). */ public class TileStoreTileProvider extends MapSourceProvider { diff --git a/src/main/java/mobac/program/commandline/CommandLineEmpty.java b/mobac/src/main/java/mobac/program/commandline/CommandLineEmpty.java similarity index 85% rename from src/main/java/mobac/program/commandline/CommandLineEmpty.java rename to mobac/src/main/java/mobac/program/commandline/CommandLineEmpty.java index 39a614c..b87ef19 100644 --- a/src/main/java/mobac/program/commandline/CommandLineEmpty.java +++ b/mobac/src/main/java/mobac/program/commandline/CommandLineEmpty.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.commandline; @@ -20,6 +20,10 @@ import mobac.program.interfaces.CommandLineAction; public class CommandLineEmpty implements CommandLineAction { + @Override + public void afterBasicInitialization() { + } + @Override public void runBeforeMainGUI() { } diff --git a/src/main/java/mobac/program/commandline/CreateAtlas.java b/mobac/src/main/java/mobac/program/commandline/CreateAtlas.java similarity index 87% rename from src/main/java/mobac/program/commandline/CreateAtlas.java rename to mobac/src/main/java/mobac/program/commandline/CreateAtlas.java index 798f6e7..cd08f61 100644 --- a/src/main/java/mobac/program/commandline/CreateAtlas.java +++ b/mobac/src/main/java/mobac/program/commandline/CreateAtlas.java @@ -1,33 +1,34 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.commandline; -import java.io.File; - -import javax.xml.bind.JAXBException; - +import jakarta.xml.bind.JAXBException; import mobac.program.AtlasThread; import mobac.program.interfaces.AtlasInterface; import mobac.program.interfaces.CommandLineAction; import mobac.program.model.Profile; import mobac.utilities.GUIExceptionHandler; +import java.io.File; + public class CreateAtlas implements CommandLineAction { + public static final String CMD_ARG = "create"; + private final String profileName; private final File outputDir; @@ -45,8 +46,13 @@ public class CreateAtlas implements CommandLineAction { System.exit(1); } outputDir = dir; - } else + } else { outputDir = null; + } + } + + @Override + public void afterBasicInitialization() { } @Override @@ -67,8 +73,9 @@ public class CreateAtlas implements CommandLineAction { System.exit(1); } AtlasThread atlasThread = new AtlasThread(atlas); - if (outputDir != null) + if (outputDir != null) { atlasThread.setCustomAtlasDir(outputDir); + } atlasThread.setQuitMobacAfterAtlasCreation(true); atlasThread.start(); } catch (Exception e) { diff --git a/mobac/src/main/java/mobac/program/commandline/PrintPublicKeyHash.java b/mobac/src/main/java/mobac/program/commandline/PrintPublicKeyHash.java new file mode 100644 index 0000000..33e0deb --- /dev/null +++ b/mobac/src/main/java/mobac/program/commandline/PrintPublicKeyHash.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.commandline; + +import mobac.program.download.MobacTrustManager; + +public class PrintPublicKeyHash extends CommandLineEmpty { + + public static final String CMD_ARG = "keyhash"; + + private String serverUrl; + + public PrintPublicKeyHash(String serverUrl) { + super(); + this.serverUrl = serverUrl; + } + + @Override + public boolean showSplashScreen() { + return false; + } + + @Override + public boolean showMainGUI() { + return false; + } + + @Override + public void afterBasicInitialization() { + serverUrl = serverUrl.toLowerCase(); + if (!serverUrl.startsWith("https://")) { + serverUrl = "https://" + serverUrl; + } + String hash; + try { + hash = MobacTrustManager.getServerPublicKeyHash(serverUrl); + System.out.println("Server: " + serverUrl); + System.out.println("Public Key Hash: " + hash); + } catch (Exception e) { + e.printStackTrace(); + } + System.exit(0); + } + +} diff --git a/src/main/java/mobac/program/download/DownloadJob.java b/mobac/src/main/java/mobac/program/download/DownloadJob.java similarity index 92% rename from src/main/java/mobac/program/download/DownloadJob.java rename to mobac/src/main/java/mobac/program/download/DownloadJob.java index 24872ab..074fb1f 100644 --- a/src/main/java/mobac/program/download/DownloadJob.java +++ b/mobac/src/main/java/mobac/program/download/DownloadJob.java @@ -1,24 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.download; -import java.net.ConnectException; -import java.net.SocketTimeoutException; - import mobac.exceptions.DownloadFailedException; import mobac.exceptions.StopAllDownloadsException; import mobac.exceptions.UnrecoverableDownloadException; @@ -29,21 +26,22 @@ import mobac.program.interfaces.DownloadJobListener; import mobac.program.interfaces.MapSource; import mobac.program.interfaces.MapSource.LoadMethod; import mobac.utilities.tar.TarIndexedArchive; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Logger; +import java.net.ConnectException; +import java.net.SocketTimeoutException; public class DownloadJob implements Job { - static Logger log = Logger.getLogger(DownloadJob.class); - - int errorCounter = 0; - + private static final Logger log = LoggerFactory.getLogger(DownloadJob.class); final MapSource mapSource; final int xValue; final int yValue; final int zoomValue; final TarIndexedArchive tileArchive; final DownloadJobListener listener; + int errorCounter = 0; public DownloadJob(MapSource mapSource, int xValue, int yValue, int zoomValue, TarIndexedArchive tileArchive, DownloadJobListener listener) { diff --git a/src/main/java/mobac/program/download/DownloadJobProducerThread.java b/mobac/src/main/java/mobac/program/download/DownloadJobProducerThread.java similarity index 86% rename from src/main/java/mobac/program/download/DownloadJobProducerThread.java rename to mobac/src/main/java/mobac/program/download/DownloadJobProducerThread.java index cda6f3a..1a02054 100644 --- a/src/main/java/mobac/program/download/DownloadJobProducerThread.java +++ b/mobac/src/main/java/mobac/program/download/DownloadJobProducerThread.java @@ -1,31 +1,30 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.download; -import java.util.Enumeration; - import mobac.program.AtlasThread; import mobac.program.JobDispatcher; import mobac.program.JobDispatcher.Job; import mobac.program.interfaces.DownloadableElement; import mobac.utilities.tar.TarIndexedArchive; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Logger; - +import java.util.Enumeration; /** * Creates the jobs for downloading tiles. If the job queue is full it will @@ -33,11 +32,9 @@ import org.apache.log4j.Logger; */ public class DownloadJobProducerThread extends Thread { - private Logger log = Logger.getLogger(DownloadJobProducerThread.class); - final JobDispatcher downloadJobDispatcher; - final Enumeration jobEnumerator; + private final Logger log = LoggerFactory.getLogger(DownloadJobProducerThread.class); public DownloadJobProducerThread(AtlasThread atlasThread, JobDispatcher downloadJobDispatcher, TarIndexedArchive tileArchive, DownloadableElement de) { @@ -52,7 +49,7 @@ public class DownloadJobProducerThread extends Thread { while (jobEnumerator.hasMoreElements()) { Job job = jobEnumerator.nextElement(); downloadJobDispatcher.addJob(job); - log.trace("Job added: " + job); + log.trace("Job added: {}", job); } log.debug("All download jobs has been generated"); } catch (InterruptedException e) { diff --git a/mobac/src/main/java/mobac/program/download/MobacSSLHelper.java b/mobac/src/main/java/mobac/program/download/MobacSSLHelper.java new file mode 100644 index 0000000..2f366b6 --- /dev/null +++ b/mobac/src/main/java/mobac/program/download/MobacSSLHelper.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.download; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.Set; + +public class MobacSSLHelper { + + public static SSLSocketFactory createSSLSocketFactory(Set additionalTrustedPublicKeys) { + MobacTrustManager trustManager = new MobacTrustManager(additionalTrustedPublicKeys); + SSLContext sslcontext; + try { + sslcontext = SSLContext.getInstance("TLS"); + sslcontext.init(new KeyManager[0], new TrustManager[]{trustManager}, null); + return sslcontext.getSocketFactory(); + } catch (NoSuchAlgorithmException | KeyManagementException e) { + throw new RuntimeException(e); + } + } +} diff --git a/mobac/src/main/java/mobac/program/download/MobacTrustManager.java b/mobac/src/main/java/mobac/program/download/MobacTrustManager.java new file mode 100644 index 0000000..1cadda3 --- /dev/null +++ b/mobac/src/main/java/mobac/program/download/MobacTrustManager.java @@ -0,0 +1,176 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.download; + +import mobac.exceptions.NotImplementedException; +import org.apache.commons.codec.binary.Hex; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; +import java.io.IOException; +import java.net.URL; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Set; + +/** + * Custom delegating {@link TrustManager} that allows to specify public key + * hashes of leaf certificates to directly trust the certificate. + *

      + * The following OpenSSL command can be used to generate the public key SHA-256 + * hash: + * + *

      + * openssl s_client -host maps.example.org -port 443 | openssl x509 -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256
      + * 
      + */ +public class MobacTrustManager implements X509TrustManager { + + private static final Logger log = LoggerFactory.getLogger(MobacTrustManager.class); + + private final X509TrustManager defaultTrustManager; + + private final Set additionalTrustedPublicKeys; + + public MobacTrustManager() { + this(null); + } + + public MobacTrustManager(Set additionalTrustedPublicKeys) { + super(); + this.additionalTrustedPublicKeys = additionalTrustedPublicKeys; + TrustManagerFactory tmf; + try { + tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init((KeyStore) null); + } catch (KeyStoreException | NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + X509TrustManager defaultTm = null; + for (TrustManager tm : tmf.getTrustManagers()) { + if (tm instanceof X509TrustManager) { + defaultTm = (X509TrustManager) tm; + break; + } + } + if (defaultTm == null) { + throw new RuntimeException("Failed to get default TrustManager"); + } + defaultTrustManager = defaultTm; + } + + private static String getPublicKeySha256Hash(X509Certificate cert) { + byte[] pubKeyData = cert.getPublicKey().getEncoded(); + try { + byte[] digest = MessageDigest.getInstance("SHA-256").digest(pubKeyData); + return Hex.encodeHexString(digest).toLowerCase(); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + public static String getServerPublicKeyHash(String serverUrl) + throws IOException, KeyManagementException, NoSuchAlgorithmException { + URL url = new URL(serverUrl); + + SSLContext sslcontext = SSLContext.getInstance("TLS"); + GetPublicKeyHashTrustManager trustManager = new GetPublicKeyHashTrustManager(); + sslcontext.init(new KeyManager[0], new TrustManager[]{trustManager}, null); + + HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); + conn.setSSLSocketFactory(sslcontext.getSocketFactory()); + try { + conn.connect(); + throw new RuntimeException("Unreachable code reached"); + } catch (SSLHandshakeException e) { + // It is expected that we end up here + if (trustManager.serverPublicKeyHash == null) { + throw new RuntimeException("Unable to get server certificate: " + e.getMessage(), e); + } + } + return trustManager.serverPublicKeyHash; + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + throw new NotImplementedException(); + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + try { + defaultTrustManager.checkServerTrusted(chain, authType); + } catch (CertificateException e) { + X509Certificate cert = chain[0]; // get the leaf certificate + log.error("SSL error: {}", e.getMessage()); + synchronized (this) { + String pubKeySha256Hash = getPublicKeySha256Hash(cert); + if (isCertificateTrusted(pubKeySha256Hash)) { + return; // certificate is trusted + } + // TODO: Add GUI for manually adding this certificate as trusted. + String message = "Untrusted certificate encountered: publicKeyHash=\"" + pubKeySha256Hash + + "\"; certificate issued for " + cert.getSubjectX500Principal(); + throw new CertificateException(message); + } + } + } + + private boolean isCertificateTrusted(String pubKeySha256Hash) { + if (additionalTrustedPublicKeys != null) { + return additionalTrustedPublicKeys.contains(pubKeySha256Hash); + } + return false; + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return defaultTrustManager.getAcceptedIssuers(); + } + + private static class GetPublicKeyHashTrustManager implements X509TrustManager { + public String serverPublicKeyHash = null; + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + X509Certificate cert = chain[0]; + serverPublicKeyHash = getPublicKeySha256Hash(cert); + throw new CertificateException(); + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + } +} diff --git a/src/main/java/mobac/program/download/TileDownLoader.java b/mobac/src/main/java/mobac/program/download/TileDownLoader.java similarity index 64% rename from src/main/java/mobac/program/download/TileDownLoader.java rename to mobac/src/main/java/mobac/program/download/TileDownLoader.java index a00978f..afc28f6 100644 --- a/src/main/java/mobac/program/download/TileDownLoader.java +++ b/mobac/src/main/java/mobac/program/download/TileDownLoader.java @@ -1,26 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.download; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.ProtocolException; - import mobac.exceptions.DownloadFailedException; import mobac.exceptions.UnrecoverableDownloadException; import mobac.program.interfaces.HttpMapSource; @@ -31,34 +26,47 @@ import mobac.program.model.TileImageType; import mobac.program.tilestore.TileStore; import mobac.program.tilestore.TileStoreEntry; import mobac.utilities.Utilities; +import mobac.utilities.imageio.ImageFormatDetector; import mobac.utilities.stream.ThrottledInputStream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import org.apache.log4j.Logger; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; public class TileDownLoader { - public static String ACCEPT = "text/html, image/png, image/jpeg, image/gif, */*;q=0.1"; + private static final Logger log = LoggerFactory.getLogger(TileDownLoader.class); static { Object defaultReadTimeout = System.getProperty("sun.net.client.defaultReadTimeout"); - if (defaultReadTimeout == null) + if (defaultReadTimeout == null) { System.setProperty("sun.net.client.defaultReadTimeout", "15000"); + } System.setProperty("http.maxConnections", "20"); + + // Disable restricted headers: By default some headers can't be set + // see https://stackoverflow.com/questions/8335501 + System.setProperty("sun.net.http.allowRestrictedHeaders", "true"); } - private static Logger log = Logger.getLogger(TileDownLoader.class); + public static void init() { + // This method is empty. It is just for enforcing execution of the static code + // block above + } - private static Settings settings = Settings.getInstance(); - - public static byte[] getImage(int x, int y, int zoom, HttpMapSource mapSource) throws IOException, - InterruptedException, UnrecoverableDownloadException { + public static byte[] getImage(int x, int y, int zoom, HttpMapSource mapSource) + throws IOException, InterruptedException, UnrecoverableDownloadException { MapSpace mapSpace = mapSource.getMapSpace(); int maxTileIndex = mapSpace.getMaxPixels(zoom) / mapSpace.getTileSize(); - if (x > maxTileIndex) + if (x > maxTileIndex) { throw new RuntimeException("Invalid tile index x=" + x + " for zoom " + zoom); - if (y > maxTileIndex) + } + if (y > maxTileIndex) { throw new RuntimeException("Invalid tile index y=" + y + " for zoom " + zoom); + } TileStore ts = TileStore.getInstance(); @@ -68,10 +76,8 @@ public class TileDownLoader { // if (Math.random()>0.7) throw new // IOException("intentionally download error"); - Settings s = Settings.getInstance(); - TileStoreEntry tile = null; - if (s.tileStoreEnabled) { + if (Settings.getInstance().tileStoreEnabled) { // Copy the file from the persistent tilestore instead of // downloading it from internet. @@ -79,16 +85,16 @@ public class TileDownLoader { boolean expired = isTileExpired(tile); if (tile != null) { if (expired) { - log.trace("Expired: " + mapSource.getName() + " " + tile); + log.trace("Expired: {} {}", mapSource.getName(), tile); } else { - log.trace("Tile of map source " + mapSource.getName() + " used from tilestore"); + log.trace("Tile of map source {} used from tilestore", mapSource.getName()); byte[] data = tile.getData(); notifyCachedTileUsed(data.length); return data; } } } - byte[] data = null; + byte[] data; if (tile == null) { data = downloadTileAndUpdateStore(x, y, zoom, mapSource); notifyTileDownloaded(data.length); @@ -119,8 +125,9 @@ public class TileDownLoader { } /** - * Download the tile from the web server and updates the tile store if the tile could be successfully retrieved. - * + * Download the tile from the web server and updates the tile store if the tile + * could be successfully retrieved. + * * @param x * @param y * @param zoom @@ -143,35 +150,39 @@ public class TileDownLoader { public static byte[] downloadTileAndUpdateStore(int x, int y, int zoom, HttpMapSource mapSource, boolean useTileStore) throws UnrecoverableDownloadException, IOException, InterruptedException { - if (zoom < 0) + if (zoom < 0) { throw new UnrecoverableDownloadException("Negative zoom!"); + } HttpURLConnection conn = mapSource.getTileUrlConnection(zoom, x, y); - if (conn == null) - throw new UnrecoverableDownloadException("Tile x=" + x + " y=" + y + " zoom=" + zoom - + " is not a valid tile in map source " + mapSource); + if (conn == null) { + throw new UnrecoverableDownloadException( + "Tile x=" + x + " y=" + y + " zoom=" + zoom + " is not a valid tile in map source " + mapSource); + } - log.trace("Downloading " + conn.getURL()); + log.trace("Downloading {}", conn.getURL()); - prepareConnection(conn); + mapSource.prepareConnection(conn); conn.connect(); - int code = conn.getResponseCode(); byte[] data = loadBodyDataInBuffer(conn); + int code = conn.getResponseCode(); + + if (code != HttpURLConnection.HTTP_OK) { + throw new DownloadFailedException(conn, data); + } - if (code != HttpURLConnection.HTTP_OK) - throw new DownloadFailedException(conn, code); - checkContentType(conn, data); checkContentLength(conn, data); - + String eTag = conn.getHeaderField("ETag"); long timeLastModified = conn.getLastModified(); long timeExpires = conn.getExpiration(); Utilities.checkForInterruption(); - TileImageType imageType = Utilities.getImageType(data); - if (imageType == null) + TileImageType imageType = ImageFormatDetector.getImageType(data); + if (imageType == null) { throw new UnrecoverableDownloadException("The returned image is of unknown format"); + } if (useTileStore) { TileStore.getInstance().putTileData(data, x, y, zoom, mapSource, timeLastModified, timeExpires, eTag); } @@ -187,74 +198,73 @@ public class TileDownLoader { final HttpMapSource.TileUpdate tileUpdate = mapSource.getTileUpdate(); switch (tileUpdate) { - case ETag: { - boolean unchanged = hasTileETag(tile, mapSource); - if (unchanged) { - if (log.isTraceEnabled()) - log.trace("Data unchanged on server (eTag): " + mapSource + " " + tile); - return null; + case ETag : { + boolean unchanged = hasTileETag(tile, mapSource); + if (unchanged) { + log.trace("Data unchanged on server (eTag): {} {}", mapSource, tile); + return null; + } + break; } - break; - } - case LastModified: { - boolean isNewer = isTileNewer(tile, mapSource); - if (!isNewer) { - if (log.isTraceEnabled()) - log.trace("Data unchanged on server (LastModified): " + mapSource + " " + tile); - return null; + case LastModified : { + boolean isNewer = isTileNewer(tile, mapSource); + if (!isNewer) { + log.trace("Data unchanged on server (LastModified): {} {}", mapSource, tile); + return null; + } + break; } - break; - } + default : } HttpURLConnection conn = mapSource.getTileUrlConnection(zoom, x, y); - if (conn == null) - throw new UnrecoverableDownloadException("Tile x=" + x + " y=" + y + " zoom=" + zoom - + " is not a valid tile in map source " + mapSource); + if (conn == null) { + throw new UnrecoverableDownloadException( + "Tile x=" + x + " y=" + y + " zoom=" + zoom + " is not a valid tile in map source " + mapSource); + } + log.trace("Checking {} {}", mapSource.getName(), tile); - if (log.isTraceEnabled()) - log.trace(String.format("Checking %s %s", mapSource.getName(), tile)); - - prepareConnection(conn); + mapSource.prepareConnection(conn); boolean conditionalRequest = false; switch (tileUpdate) { - case IfNoneMatch: { - if (tile.geteTag() != null) { - conn.setRequestProperty("If-None-Match", tile.geteTag()); - conditionalRequest = true; + case IfNoneMatch : { + if (tile.geteTag() != null) { + conn.setRequestProperty("If-None-Match", tile.geteTag()); + conditionalRequest = true; + } + break; } - break; - } - case IfModifiedSince: { - if (tile.getTimeLastModified() > 0) { - conn.setIfModifiedSince(tile.getTimeLastModified()); - conditionalRequest = true; + case IfModifiedSince : { + if (tile.getTimeLastModified() > 0) { + conn.setIfModifiedSince(tile.getTimeLastModified()); + conditionalRequest = true; + } + break; } - break; - } + default : } conn.connect(); - Settings s = Settings.getInstance(); - int code = conn.getResponseCode(); if (conditionalRequest && code == HttpURLConnection.HTTP_NOT_MODIFIED) { // Data unchanged on server - if (s.tileStoreEnabled) { + if (Settings.getInstance().tileStoreEnabled) { tile.update(conn.getExpiration()); TileStore.getInstance().putTile(tile, mapSource); } - if (log.isTraceEnabled()) + if (log.isTraceEnabled()) { log.trace("Data unchanged on server: " + mapSource + " " + tile); + } return null; } byte[] data = loadBodyDataInBuffer(conn); - if (code != HttpURLConnection.HTTP_OK) - throw new DownloadFailedException(conn, code); + if (code != HttpURLConnection.HTTP_OK) { + throw new DownloadFailedException(conn, data); + } checkContentType(conn, data); checkContentLength(conn, data); @@ -264,10 +274,11 @@ public class TileDownLoader { long timeExpires = conn.getExpiration(); Utilities.checkForInterruption(); - TileImageType imageType = Utilities.getImageType(data); - if (imageType == null) + TileImageType imageType = ImageFormatDetector.getImageType(data); + if (imageType == null) { throw new UnrecoverableDownloadException("The returned image is of unknown format"); - if (s.tileStoreEnabled) { + } + if (Settings.getInstance().tileStoreEnabled) { TileStore.getInstance().putTileData(data, x, y, zoom, mapSource, timeLastModified, timeExpires, eTag); } Utilities.checkForInterruption(); @@ -275,76 +286,82 @@ public class TileDownLoader { } public static boolean isTileExpired(TileStoreEntry tileStoreEntry) { - if (tileStoreEntry == null) + if (tileStoreEntry == null) { return true; + } long expiredTime = tileStoreEntry.getTimeExpires(); - if (expiredTime >= 0) { + if (expiredTime > 0) { // server had set an expiration time - long maxExpirationTime = settings.tileMaxExpirationTime + tileStoreEntry.getTimeDownloaded(); - long minExpirationTime = settings.tileMinExpirationTime + tileStoreEntry.getTimeDownloaded(); + long maxExpirationTime = Settings.getInstance().tileMaxExpirationTime + tileStoreEntry.getTimeDownloaded(); + long minExpirationTime = Settings.getInstance().tileMinExpirationTime + tileStoreEntry.getTimeDownloaded(); expiredTime = Math.max(minExpirationTime, Math.min(maxExpirationTime, expiredTime)); } else { // no expiration time set by server - use the default one - expiredTime = tileStoreEntry.getTimeDownloaded() + settings.tileDefaultExpirationTime; + expiredTime = tileStoreEntry.getTimeDownloaded() + Settings.getInstance().tileDefaultExpirationTime; } + // the tile has expired if the expiration time has passed / is in the past return (expiredTime < System.currentTimeMillis()); } /** - * Reads all available data from the input stream of conn and returns it as byte array. If no input - * data is available the method returns null. - * + * Reads all available data from the input stream of conn and + * returns it as byte array. If no input data is available the method returns + * null. + * * @param conn * @return * @throws IOException */ protected static byte[] loadBodyDataInBuffer(HttpURLConnection conn) throws IOException { - InputStream input = conn.getInputStream(); byte[] data = null; - try { + try (InputStream input = conn.getInputStream()) { + InputStream wrappedInput = input; if (Thread.currentThread() instanceof MapSourceListener) { // We only throttle atlas downloads, not downloads for the preview map long bandwidthLimit = Settings.getInstance().getBandwidthLimit(); if (bandwidthLimit > 0) { - input = new ThrottledInputStream(input); + wrappedInput = new ThrottledInputStream(input); } } - data = Utilities.getInputBytes(input); + data = Utilities.getInputBytes(wrappedInput); } catch (IOException e) { - InputStream errorIn = conn.getErrorStream(); - try { - byte[] errData = Utilities.getInputBytes(errorIn); - log.trace("Retrieved " + errData.length + " error bytes for a HTTP " + conn.getResponseCode()); - } catch (Exception ee) { - log.debug("Error retrieving error stream content: " + e); - } finally { - Utilities.closeStream(errorIn); + byte[] errData; + try (InputStream errorIn = conn.getErrorStream()) { + errData = Utilities.getInputBytes(errorIn); + log.trace("Retrieved " + errData.length + " error bytes for a HTTP " + conn.getResponseCode() + " from " + + conn.getURL()); + + } catch (Exception e1) { + log.debug("Error retrieving error stream content: " + e1); + errData = null; } - throw e; - } finally { - Utilities.closeStream(input); + throw new DownloadFailedException(conn, errData, e); } log.trace("Retrieved " + data.length + " bytes for a HTTP " + conn.getResponseCode()); - if (data.length == 0) + if (data.length == 0) { return null; + } return data; } /** - * Performs a HEAD request for retrieving the LastModified header value. + * Performs a HEAD request for retrieving the + * LastModified header value. */ protected static boolean isTileNewer(TileStoreEntry tile, HttpMapSource mapSource) throws IOException { long oldLastModified = tile.getTimeLastModified(); if (oldLastModified <= 0) { - log.warn("Tile age comparison not possible: " + "tile in tilestore does not contain lastModified attribute"); + log.warn( + "Tile age comparison not possible: " + "tile in tilestore does not contain lastModified attribute"); return true; } HttpURLConnection conn = mapSource.getTileUrlConnection(tile.getZoom(), tile.getX(), tile.getY()); conn.setRequestMethod("HEAD"); - conn.setRequestProperty("Accept", ACCEPT); + conn.setRequestProperty("Accept", Settings.getInstance().getHttpAccept()); long newLastModified = conn.getLastModified(); - if (newLastModified == 0) + if (newLastModified == 0) { return true; + } return (newLastModified > oldLastModified); } @@ -356,25 +373,16 @@ public class TileDownLoader { } HttpURLConnection conn = mapSource.getTileUrlConnection(tile.getZoom(), tile.getX(), tile.getY()); conn.setRequestMethod("HEAD"); - conn.setRequestProperty("Accept", ACCEPT); + conn.setRequestProperty("Accept", Settings.getInstance().getHttpAccept()); String onlineETag = conn.getHeaderField("ETag"); - if (onlineETag == null || onlineETag.length() == 0) + if (onlineETag == null || onlineETag.length() == 0) { return true; + } return (onlineETag.equals(eTag)); } - protected static void prepareConnection(HttpURLConnection conn) throws ProtocolException { - conn.setRequestMethod("GET"); - - Settings s = Settings.getInstance(); - conn.setConnectTimeout(1000 * s.httpConnectionTimeout); - conn.setReadTimeout(1000 * s.httpReadTimeout); - if (conn.getRequestProperty("User-agent") == null) - conn.setRequestProperty("User-agent", s.getUserAgent()); - conn.setRequestProperty("Accept", ACCEPT); - } - - protected static void checkContentType(HttpURLConnection conn, byte[] data) throws UnrecoverableDownloadException { + protected static void checkContentType(HttpURLConnection conn, byte[] data) + throws DownloadFailedException, IOException { String contentType = conn.getContentType(); if (contentType != null) { contentType = contentType.toLowerCase(); @@ -382,25 +390,28 @@ public class TileDownLoader { if (log.isTraceEnabled() && contentType.startsWith("text/")) { log.trace("Content (" + contentType + "): " + new String(data)); } - throw new UnrecoverableDownloadException("Content type of the loaded image is unknown: " + contentType, - UnrecoverableDownloadException.ERROR_CODE_CONTENT_TYPE); + throw new DownloadFailedException(conn, data); } } } /** - * Check if the retrieved data length is equal to the header value Content-Length - * + * Check if the retrieved data length is equal to the header value + * Content-Length + * * @param conn * @param data * @throws UnrecoverableDownloadException */ - protected static void checkContentLength(HttpURLConnection conn, byte[] data) throws UnrecoverableDownloadException { + protected static void checkContentLength(HttpURLConnection conn, byte[] data) + throws UnrecoverableDownloadException { int len = conn.getContentLength(); - if (len < 0) + if (len < 0) { return; - if (data.length != len) + } + if (data.length != len) { throw new UnrecoverableDownloadException("Content length is not as declared by the server: retrived=" + data.length + " bytes expected-content-length=" + len + " bytes"); + } } } diff --git a/src/main/java/mobac/program/download/UserAgent.java b/mobac/src/main/java/mobac/program/download/UserAgent.java similarity index 90% rename from src/main/java/mobac/program/download/UserAgent.java rename to mobac/src/main/java/mobac/program/download/UserAgent.java index af036bf..a4d3c02 100644 --- a/src/main/java/mobac/program/download/UserAgent.java +++ b/mobac/src/main/java/mobac/program/download/UserAgent.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.download; @@ -33,8 +33,8 @@ public class UserAgent { public static final String OPERA11_WIN7 = "Opera/9.80 (Windows NT 6.1; U; en) Presto/2.7.62 Version/11.01"; - private String name; - private String userAgent; + private final String name; + private final String userAgent; protected UserAgent(String name, String userAgent) { super(); diff --git a/src/main/java/mobac/program/download/jobenumerators/DownloadJobEnumerator.java b/mobac/src/main/java/mobac/program/download/jobenumerators/DownloadJobEnumerator.java similarity index 91% rename from src/main/java/mobac/program/download/jobenumerators/DownloadJobEnumerator.java rename to mobac/src/main/java/mobac/program/download/jobenumerators/DownloadJobEnumerator.java index cf7a70c..c9a1918 100644 --- a/src/main/java/mobac/program/download/jobenumerators/DownloadJobEnumerator.java +++ b/mobac/src/main/java/mobac/program/download/jobenumerators/DownloadJobEnumerator.java @@ -1,24 +1,21 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.download.jobenumerators; -import java.awt.Point; -import java.util.Enumeration; - import mobac.program.JobDispatcher.Job; import mobac.program.download.DownloadJob; import mobac.program.interfaces.DownloadJobListener; @@ -27,8 +24,12 @@ import mobac.program.interfaces.TileFilter; import mobac.program.model.Map; import mobac.utilities.tar.TarIndexedArchive; +import java.awt.Point; +import java.util.Enumeration; + /** - * Enumerates / creates the download jobs for a regular rectangle single layer map. + * Enumerates / creates the download jobs for a regular rectangle single layer + * map. */ public class DownloadJobEnumerator implements Enumeration { @@ -46,7 +47,7 @@ public class DownloadJobEnumerator implements Enumeration { /** * This enumerator is the unfolded version for two encapsulated loops: - * + * *
       	 * for (int y = yMin; y <= yMax; y++) {
       	 * 	for (int x = xMin; x <= xMax; x++) {
      @@ -54,7 +55,7 @@ public class DownloadJobEnumerator implements Enumeration {
       	 * 	}
       	 * }
       	 * 
      - * + * * @param map * @param tileArchive * @param listener @@ -77,8 +78,9 @@ public class DownloadJobEnumerator implements Enumeration { x = xMin; nextJob = new DownloadJob(mapSource, x, y, zoom, tileArchive, listener); - if (!tileFilter.testTile(x, y, zoom, mapSource)) + if (!tileFilter.testTile(x, y, zoom, mapSource)) { nextElement(); + } } public boolean hasMoreElements() { diff --git a/src/main/java/mobac/program/interfaces/AtlasInterface.java b/mobac/src/main/java/mobac/program/interfaces/AtlasInterface.java similarity index 67% rename from src/main/java/mobac/program/interfaces/AtlasInterface.java rename to mobac/src/main/java/mobac/program/interfaces/AtlasInterface.java index 18776f5..d2b758d 100644 --- a/src/main/java/mobac/program/interfaces/AtlasInterface.java +++ b/mobac/src/main/java/mobac/program/interfaces/AtlasInterface.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; @@ -23,27 +23,26 @@ public interface AtlasInterface extends AtlasObject, Iterable { /** * @return Number of layers in this atlas */ - public int getLayerCount(); + int getLayerCount(); /** - * * @param index * 0 - ({@link #getLayerCount()}-1) * @return */ - public LayerInterface getLayer(int index); + LayerInterface getLayer(int index); - public void addLayer(LayerInterface l); + void addLayer(LayerInterface l); - public void deleteLayer(LayerInterface l); + void deleteLayer(LayerInterface l); - public void setOutputFormat(AtlasOutputFormat atlasOutputFormat); + AtlasOutputFormat getOutputFormat(); - public AtlasOutputFormat getOutputFormat(); + void setOutputFormat(AtlasOutputFormat atlasOutputFormat); - public long calculateTilesToDownload(); + long calculateTilesToDownload(); - public int getVersion(); - - public AtlasInterface deepClone(); + int getVersion(); + + AtlasInterface deepClone(); } diff --git a/src/main/java/mobac/program/interfaces/AtlasObject.java b/mobac/src/main/java/mobac/program/interfaces/AtlasObject.java similarity index 63% rename from src/main/java/mobac/program/interfaces/AtlasObject.java rename to mobac/src/main/java/mobac/program/interfaces/AtlasObject.java index ec6acd6..f0b6d2d 100644 --- a/src/main/java/mobac/program/interfaces/AtlasObject.java +++ b/mobac/src/main/java/mobac/program/interfaces/AtlasObject.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; @@ -24,19 +24,42 @@ import mobac.exceptions.InvalidNameException; */ public interface AtlasObject { - public String getName(); + String getName(); - public void setName(String newName) throws InvalidNameException; + void setName(String newName) throws InvalidNameException; /** * Called after loading the complete atlas from a profile. - * + * * @return any problems found? true=yes */ - public boolean checkData(); + boolean checkData(); - public double getMinLat(); - public double getMaxLat(); - public double getMinLon(); - public double getMaxLon(); + /** + * minimum latitude (corresponds to row/y value) + * + * @return + */ + double getMinLat(); + + /** + * maximum latitude (corresponds to row/y value) + * + * @return + */ + double getMaxLat(); + + /** + * minimum longitude (corresponds to column/x value) + * + * @return + */ + double getMinLon(); + + /** + * maximum longitude (corresponds to column/x value) + * + * @return + */ + double getMaxLon(); } diff --git a/src/main/java/mobac/program/interfaces/CapabilityDeletable.java b/mobac/src/main/java/mobac/program/interfaces/CapabilityDeletable.java similarity index 89% rename from src/main/java/mobac/program/interfaces/CapabilityDeletable.java rename to mobac/src/main/java/mobac/program/interfaces/CapabilityDeletable.java index 8480376..77e7814 100644 --- a/src/main/java/mobac/program/interfaces/CapabilityDeletable.java +++ b/mobac/src/main/java/mobac/program/interfaces/CapabilityDeletable.java @@ -1,18 +1,18 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; @@ -26,5 +26,5 @@ import mobac.program.model.AtlasTreeModel; */ public interface CapabilityDeletable { - public void delete(); + void delete(); } diff --git a/mobac/src/main/java/mobac/program/interfaces/CloneableMapSource.java b/mobac/src/main/java/mobac/program/interfaces/CloneableMapSource.java new file mode 100644 index 0000000..1a3908f --- /dev/null +++ b/mobac/src/main/java/mobac/program/interfaces/CloneableMapSource.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.interfaces; + +public interface CloneableMapSource extends Cloneable { + MapSource clone() throws CloneNotSupportedException; +} diff --git a/src/main/java/mobac/program/interfaces/CommandLineAction.java b/mobac/src/main/java/mobac/program/interfaces/CommandLineAction.java similarity index 76% rename from src/main/java/mobac/program/interfaces/CommandLineAction.java rename to mobac/src/main/java/mobac/program/interfaces/CommandLineAction.java index 61db376..01ff188 100644 --- a/src/main/java/mobac/program/interfaces/CommandLineAction.java +++ b/mobac/src/main/java/mobac/program/interfaces/CommandLineAction.java @@ -1,28 +1,31 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; public interface CommandLineAction { - public boolean showSplashScreen(); - - public boolean showMainGUI(); - - public void runBeforeMainGUI(); + boolean showSplashScreen(); + + boolean showMainGUI(); + + void afterBasicInitialization(); + + void runBeforeMainGUI(); + + void runMainGUI(); - public void runMainGUI(); } diff --git a/src/main/java/mobac/program/interfaces/DownloadJobListener.java b/mobac/src/main/java/mobac/program/interfaces/DownloadJobListener.java similarity index 74% rename from src/main/java/mobac/program/interfaces/DownloadJobListener.java rename to mobac/src/main/java/mobac/program/interfaces/DownloadJobListener.java index 7120b71..e438058 100644 --- a/src/main/java/mobac/program/interfaces/DownloadJobListener.java +++ b/mobac/src/main/java/mobac/program/interfaces/DownloadJobListener.java @@ -1,29 +1,29 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; public interface DownloadJobListener { - - public int getMaxDownloadRetries(); - - public void jobStarted(); - public void jobFinishedSuccessfully(int bytesDownloaded); + int getMaxDownloadRetries(); - public void jobFinishedWithError(boolean retry); + void jobStarted(); + + void jobFinishedSuccessfully(int bytesDownloaded); + + void jobFinishedWithError(boolean retry); } diff --git a/src/main/java/mobac/program/interfaces/DownloadableElement.java b/mobac/src/main/java/mobac/program/interfaces/DownloadableElement.java similarity index 83% rename from src/main/java/mobac/program/interfaces/DownloadableElement.java rename to mobac/src/main/java/mobac/program/interfaces/DownloadableElement.java index dd0430a..d6b74d3 100644 --- a/src/main/java/mobac/program/interfaces/DownloadableElement.java +++ b/mobac/src/main/java/mobac/program/interfaces/DownloadableElement.java @@ -1,46 +1,42 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; -import java.util.Enumeration; - import mobac.program.JobDispatcher.Job; import mobac.utilities.tar.TarIndexedArchive; +import java.util.Enumeration; /** * Classes that implement this interface identify themselves as responsible for * specifying what tiles should be downloaded. - * + *

      * In general this interface should be implemented in combination with * {@link MapInterface}, {@link LayerInterface} or {@link AtlasInterface}. - * */ public interface DownloadableElement { /** - * * @param tileArchive * @param listener * @return An enumeration that returns {@link Job} objects. Each job should - * download one map tile from the providing web server (or from the - * tile cache). + * download one map tile from the providing web server (or from the tile + * cache). */ - public Enumeration getDownloadJobs(TarIndexedArchive tileArchive, - DownloadJobListener listener); - + Enumeration getDownloadJobs(TarIndexedArchive tileArchive, DownloadJobListener listener); + } diff --git a/src/main/java/mobac/program/interfaces/ExceptionExtendedInfo.java b/mobac/src/main/java/mobac/program/interfaces/ExceptionExtendedInfo.java similarity index 85% rename from src/main/java/mobac/program/interfaces/ExceptionExtendedInfo.java rename to mobac/src/main/java/mobac/program/interfaces/ExceptionExtendedInfo.java index 1291454..4a52d9b 100644 --- a/src/main/java/mobac/program/interfaces/ExceptionExtendedInfo.java +++ b/mobac/src/main/java/mobac/program/interfaces/ExceptionExtendedInfo.java @@ -1,22 +1,22 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; public interface ExceptionExtendedInfo { - public String getExtendedInfo(); + String getExtendedInfo(); } diff --git a/src/main/java/mobac/program/interfaces/FileBasedMapSource.java b/mobac/src/main/java/mobac/program/interfaces/FileBasedMapSource.java similarity index 80% rename from src/main/java/mobac/program/interfaces/FileBasedMapSource.java rename to mobac/src/main/java/mobac/program/interfaces/FileBasedMapSource.java index 40dd846..003d038 100644 --- a/src/main/java/mobac/program/interfaces/FileBasedMapSource.java +++ b/mobac/src/main/java/mobac/program/interfaces/FileBasedMapSource.java @@ -1,27 +1,27 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; /** - * Marker interface for file based map sources (map sources that use tiles present in the file system and therefore do - * not stress online tile servers. + * Marker interface for file based map sources (map sources that use tiles + * present in the file system and therefore do not stress online tile servers. */ public interface FileBasedMapSource extends InitializableMapSource { - public void reinitialize(); + void reinitialize(); } diff --git a/src/main/java/mobac/program/interfaces/HttpMapSource.java b/mobac/src/main/java/mobac/program/interfaces/HttpMapSource.java similarity index 60% rename from src/main/java/mobac/program/interfaces/HttpMapSource.java rename to mobac/src/main/java/mobac/program/interfaces/HttpMapSource.java index 79a7e2f..b715665 100644 --- a/src/main/java/mobac/program/interfaces/HttpMapSource.java +++ b/mobac/src/main/java/mobac/program/interfaces/HttpMapSource.java @@ -1,63 +1,73 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; import java.io.IOException; import java.net.HttpURLConnection; +import java.net.ProtocolException; public interface HttpMapSource extends MapSource { - /** - * Specifies the different mechanisms for detecting updated tiles respectively only download newer tiles than those - * stored locally. - * - *

        - *
      • {@link #IfNoneMatch} Server provides ETag header entry for all tiles and supports conditional download - * via If-None-Match header entry.
      • - *
      • {@link #ETag} Server provides ETag header entry for all tiles but does not support conditional - * download via If-None-Match header entry.
      • - *
      • {@link #IfModifiedSince} Server provides Last-Modified header entry for all tiles and supports - * conditional download via If-Modified-Since header entry.
      • - *
      • {@link #LastModified} Server provides Last-Modified header entry for all tiles but does not support - * conditional download via If-Modified-Since header entry.
      • - *
      • {@link #None} The server does not support any of the listed mechanisms.
      • - *
      - * - */ - public enum TileUpdate { - IfNoneMatch, ETag, IfModifiedSince, LastModified, None - } - /** * @return The supported tile update mechanism * @see TileUpdate */ - public TileUpdate getTileUpdate(); + TileUpdate getTileUpdate(); + + String getTileUrl(int zoom, int tilex, int tiley); /** - * Constructs the tile url connection. If necessary the url connection can be prepared with cookies or other http - * specific headers which are required by the http server. - * + * Constructs the tile url connection. If necessary the url connection can be + * prepared with cookies or other http specific headers which are required by + * the http server. + * * @param zoom * @param tilex * tile number on x-axis for the specified zoom level * @param tiley * tile number on y-axis for the specified zoom level - * @return the initialized urlConnection for downloading the specified tile image + * @return the initialized urlConnection for downloading the specified tile + * image */ - public HttpURLConnection getTileUrlConnection(int zoom, int tilex, int tiley) throws IOException; + HttpURLConnection getTileUrlConnection(int zoom, int tilex, int tiley) throws IOException; + void prepareConnection(HttpURLConnection connection) throws ProtocolException; + + /** + * Specifies the different mechanisms for detecting updated tiles respectively + * only download newer tiles than those stored locally. + * + *
        + *
      • {@link #IfNoneMatch} Server provides ETag header entry for all tiles and + * supports conditional download via If-None-Match header + * entry.
      • + *
      • {@link #ETag} Server provides ETag header entry for all tiles but does + * not support conditional download via If-None-Match header + * entry.
      • + *
      • {@link #IfModifiedSince} Server provides Last-Modified header entry for + * all tiles and supports conditional download via + * If-Modified-Since header entry.
      • + *
      • {@link #LastModified} Server provides Last-Modified header entry for all + * tiles but does not support conditional download via + * If-Modified-Since header entry.
      • + *
      • {@link #None} The server does not support any of the listed + * mechanisms.
      • + *
      + */ + enum TileUpdate { + IfNoneMatch, ETag, IfModifiedSince, LastModified, None + } } diff --git a/src/main/java/mobac/program/interfaces/InitializableMapSource.java b/mobac/src/main/java/mobac/program/interfaces/InitializableMapSource.java similarity index 79% rename from src/main/java/mobac/program/interfaces/InitializableMapSource.java rename to mobac/src/main/java/mobac/program/interfaces/InitializableMapSource.java index b21d86d..2d9b883 100644 --- a/src/main/java/mobac/program/interfaces/InitializableMapSource.java +++ b/mobac/src/main/java/mobac/program/interfaces/InitializableMapSource.java @@ -1,23 +1,25 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; +import mobac.exceptions.MapSourceInitializationException; + public interface InitializableMapSource extends MapSource { - public void initialize(); - + void initialize() throws MapSourceInitializationException; + } diff --git a/src/main/java/mobac/program/interfaces/LayerInterface.java b/mobac/src/main/java/mobac/program/interfaces/LayerInterface.java similarity index 68% rename from src/main/java/mobac/program/interfaces/LayerInterface.java rename to mobac/src/main/java/mobac/program/interfaces/LayerInterface.java index e1f58d0..669119b 100644 --- a/src/main/java/mobac/program/interfaces/LayerInterface.java +++ b/mobac/src/main/java/mobac/program/interfaces/LayerInterface.java @@ -1,33 +1,35 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; -public interface LayerInterface extends AtlasObject, Iterable, CapabilityDeletable { +import javax.swing.tree.TreeNode; - public void addMap(MapInterface map); +public interface LayerInterface extends AtlasObject, Iterable, CapabilityDeletable, TreeNode { - public int getMapCount(); + void addMap(MapInterface map); - public MapInterface getMap(int index); + int getMapCount(); - public AtlasInterface getAtlas(); + MapInterface getMap(int index); - public long calculateTilesToDownload(); + AtlasInterface getAtlas(); - public LayerInterface deepClone(AtlasInterface atlas); + long calculateTilesToDownload(); + + LayerInterface deepClone(AtlasInterface atlas); } diff --git a/src/main/java/mobac/program/interfaces/MapInterface.java b/mobac/src/main/java/mobac/program/interfaces/MapInterface.java similarity index 59% rename from src/main/java/mobac/program/interfaces/MapInterface.java rename to mobac/src/main/java/mobac/program/interfaces/MapInterface.java index 7ff0590..4f76813 100644 --- a/src/main/java/mobac/program/interfaces/MapInterface.java +++ b/mobac/src/main/java/mobac/program/interfaces/MapInterface.java @@ -1,54 +1,53 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; +import mobac.program.model.TileImageParameters; + +import javax.swing.tree.TreeNode; import java.awt.Dimension; import java.awt.Point; -import mobac.program.model.TileImageParameters; +public interface MapInterface extends AtlasObject, CapabilityDeletable, TreeNode { + Point getMinTileCoordinate(); + Point getMaxTileCoordinate(); -public interface MapInterface extends AtlasObject, CapabilityDeletable { + int getZoom(); - public Point getMinTileCoordinate(); + MapSource getMapSource(); - public Point getMaxTileCoordinate(); + Dimension getTileSize(); - public int getZoom(); + LayerInterface getLayer(); - public MapSource getMapSource(); + void setLayer(LayerInterface layer); - public Dimension getTileSize(); + TileImageParameters getParameters(); - public LayerInterface getLayer(); + void setParameters(TileImageParameters p); - public void setLayer(LayerInterface layer); + long calculateTilesToDownload(); - public TileImageParameters getParameters(); + String getInfoText(); - public void setParameters(TileImageParameters p); + TileFilter getTileFilter(); - public long calculateTilesToDownload(); - - public String getInfoText(); - - public TileFilter getTileFilter(); - - public MapInterface deepClone(LayerInterface newLayer); + MapInterface deepClone(LayerInterface newLayer); } diff --git a/src/main/java/mobac/program/interfaces/MapSource.java b/mobac/src/main/java/mobac/program/interfaces/MapSource.java similarity index 64% rename from src/main/java/mobac/program/interfaces/MapSource.java rename to mobac/src/main/java/mobac/program/interfaces/MapSource.java index d92dfb6..9e3d9c3 100644 --- a/src/main/java/mobac/program/interfaces/MapSource.java +++ b/mobac/src/main/java/mobac/program/interfaces/MapSource.java @@ -1,28 +1,23 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; -import java.awt.Color; -import java.awt.image.BufferedImage; -import java.io.IOException; - -import javax.xml.bind.annotation.XmlTransient; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; - +import jakarta.xml.bind.annotation.XmlTransient; +import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import mobac.exceptions.TileException; import mobac.exceptions.UnrecoverableDownloadException; import mobac.gui.mapview.JMapViewer; @@ -30,43 +25,45 @@ import mobac.program.jaxb.MapSourceAdapter; import mobac.program.model.MapSourceLoaderInfo; import mobac.program.model.TileImageType; +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.IOException; + //License: GPL. Copyright 2008 by Jan Peter Stotz /** - * * @author Jan Peter Stotz */ @XmlJavaTypeAdapter(MapSourceAdapter.class) public interface MapSource { - public enum LoadMethod { - DEFAULT, CACHE, SOURCE - }; - /** - * Specifies the maximum zoom value. The number of zoom levels is [0.. {@link #getMaxZoom()}]. - * - * @return maximum zoom value that has to be smaller or equal to {@link JMapViewer#MAX_ZOOM} + * Specifies the maximum zoom value. The number of zoom levels is [0.. + * {@link #getMaxZoom()}]. + * + * @return maximum zoom value that has to be smaller or equal to + * {@link JMapViewer#MAX_ZOOM} */ - public int getMaxZoom(); + int getMaxZoom(); /** - * Specifies the minimum zoom value. This value is usually 0. Only for maps that cover a certain region up to a - * limited zoom level this method should return a value different than 0. - * + * Specifies the minimum zoom value. This value is usually 0. Only for maps that + * cover a certain region up to a limited zoom level this method should return a + * value different than 0. + * * @return minimum zoom value - usually 0 */ - public int getMinZoom(); + int getMinZoom(); /** - * A tile layer name has to be unique and has to consist only of characters valid for filenames. - * + * A tile layer name has to be unique and has to consist only of characters + * valid for filenames. + * * @return Name of the tile layer */ - public String getName(); + String getName(); /** - * * @param zoom * @param x * @param y @@ -77,11 +74,10 @@ public interface MapSource { * @throws InterruptedException * @throws UnrecoverableDownloadException */ - public byte[] getTileData(int zoom, int x, int y, LoadMethod loadMethod) throws IOException, TileException, - InterruptedException; + byte[] getTileData(int zoom, int x, int y, LoadMethod loadMethod) + throws IOException, TileException, InterruptedException; /** - * * @param zoom * @param x * @param y @@ -91,24 +87,28 @@ public interface MapSource { * @throws UnrecoverableDownloadException * @throws InterruptedException */ - public BufferedImage getTileImage(int zoom, int x, int y, LoadMethod loadMethod) throws IOException, TileException, - InterruptedException; + BufferedImage getTileImage(int zoom, int x, int y, LoadMethod loadMethod) + throws IOException, TileException, InterruptedException; /** - * Specifies the tile image type. For tiles rendered by Mapnik or Osmarenderer this is usually - * {@link TileImageType#PNG}. - * + * Specifies the tile image type. For tiles rendered by Mapnik or Osmarenderer + * this is usually {@link TileImageType#PNG}. + * * @return file extension of the tile image type */ - public TileImageType getTileImageType(); + TileImageType getTileImageType(); - public MapSpace getMapSpace(); + MapSpace getMapSpace(); - public Color getBackgroundColor(); + Color getBackgroundColor(); @XmlTransient - public MapSourceLoaderInfo getLoaderInfo(); + MapSourceLoaderInfo getLoaderInfo(); - public void setLoaderInfo(MapSourceLoaderInfo loaderInfo); + void setLoaderInfo(MapSourceLoaderInfo loaderInfo); + + enum LoadMethod { + DEFAULT, CACHE, SOURCE + } } diff --git a/src/main/java/mobac/mapsources/custom/CustomMapSourceType.java b/mobac/src/main/java/mobac/program/interfaces/MapSourceCallerThreadInfo.java similarity index 78% rename from src/main/java/mobac/mapsources/custom/CustomMapSourceType.java rename to mobac/src/main/java/mobac/program/interfaces/MapSourceCallerThreadInfo.java index 42fb53a..1dbfdcc 100644 --- a/src/main/java/mobac/mapsources/custom/CustomMapSourceType.java +++ b/mobac/src/main/java/mobac/program/interfaces/MapSourceCallerThreadInfo.java @@ -1,21 +1,22 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ -package mobac.mapsources.custom; +package mobac.program.interfaces; -public enum CustomMapSourceType { - DIR_ZOOM_X_Y, DIR_ZOOM_Y_X, QUADKEY; +public interface MapSourceCallerThreadInfo { + + boolean isMapPreviewThread(); } diff --git a/mobac/src/main/java/mobac/program/interfaces/MapSourceInitialDisplayPosition.java b/mobac/src/main/java/mobac/program/interfaces/MapSourceInitialDisplayPosition.java new file mode 100644 index 0000000..1566bdb --- /dev/null +++ b/mobac/src/main/java/mobac/program/interfaces/MapSourceInitialDisplayPosition.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.interfaces; + +import mobac.gui.mapview.PreviewMap; + +/** + * For the MOBAC {@link PreviewMap}: Allows to specify the initial view point of + * a map source on it's {@link MapSource#getMinZoom()} zoom level. + */ +public interface MapSourceInitialDisplayPosition { + + int getInitialDisplayPositionX(); + + int getInitialDisplayPositionY(); +} diff --git a/src/main/java/mobac/program/interfaces/MapSourceListener.java b/mobac/src/main/java/mobac/program/interfaces/MapSourceListener.java similarity index 78% rename from src/main/java/mobac/program/interfaces/MapSourceListener.java rename to mobac/src/main/java/mobac/program/interfaces/MapSourceListener.java index 07edf17..3f7216f 100644 --- a/src/main/java/mobac/program/interfaces/MapSourceListener.java +++ b/mobac/src/main/java/mobac/program/interfaces/MapSourceListener.java @@ -1,24 +1,26 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; public interface MapSourceListener { - public void tileDownloaded(int size); - - public void tileLoadedFromCache(int size); + void tileDownloadStarted(String tileUrl); + + void tileDownloaded(int size); + + void tileLoadedFromCache(int size); } diff --git a/src/main/java/mobac/program/interfaces/MapSourceTextAttribution.java b/mobac/src/main/java/mobac/program/interfaces/MapSourceTextAttribution.java similarity index 83% rename from src/main/java/mobac/program/interfaces/MapSourceTextAttribution.java rename to mobac/src/main/java/mobac/program/interfaces/MapSourceTextAttribution.java index 9a10cc4..5dc3f82 100644 --- a/src/main/java/mobac/program/interfaces/MapSourceTextAttribution.java +++ b/mobac/src/main/java/mobac/program/interfaces/MapSourceTextAttribution.java @@ -1,27 +1,27 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; public interface MapSourceTextAttribution { - public String getAttributionText(); + String getAttributionText(); /** * @return The URL to open when the user clicks the attribution image. */ - public String getAttributionLinkURL(); + String getAttributionLinkURL(); } diff --git a/src/main/java/mobac/program/interfaces/MapSpace.java b/mobac/src/main/java/mobac/program/interfaces/MapSpace.java similarity index 70% rename from src/main/java/mobac/program/interfaces/MapSpace.java rename to mobac/src/main/java/mobac/program/interfaces/MapSpace.java index a74139e..523bcdb 100644 --- a/src/main/java/mobac/program/interfaces/MapSpace.java +++ b/mobac/src/main/java/mobac/program/interfaces/MapSpace.java @@ -1,29 +1,29 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; -import java.awt.Point; - import mobac.mapsources.mapspace.MercatorPower2MapSpace; +import java.awt.Point; + /** * Preparation for supporting map resolutions other than those uses by * Google/OpenstreetMap. - * + *

      * {@link MercatorPower2MapSpace} is the only implementation that is currently * supported by Mobile Atlas Creator. *

      @@ -32,61 +32,56 @@ import mobac.mapsources.mapspace.MercatorPower2MapSpace; */ public interface MapSpace { - public enum ProjectionCategory { - SPHERE, ELLIPSOID, GEOID - }; + ProjectionCategory getProjectionCategory(); - public ProjectionCategory getProjectionCategory(); - - public int getMaxPixels(int zoom); + int getMaxPixels(int zoom); /** * @return size (height and width) of each tile in pixel */ - public int getTileSize(); + int getTileSize(); /** * Converts the horizontal pixel coordinate from map space to longitude. - * + * * @param lon * @param zoom * @return */ - public int cLonToX(double lon, int zoom); + int cLonToX(double lon, int zoom); /** * Converts the vertical pixel coordinate from map space to latitude. - * + * * @param lat * @param zoom * @return */ - public int cLatToY(double lat, int zoom); + int cLatToY(double lat, int zoom); /** * Converts longitude to the horizontal pixel coordinate from map space. - * + * * @param x * @param zoom * @return */ - public double cXToLon(int x, int zoom); + double cXToLon(int x, int zoom); /** * Converts latitude to the vertical pixel coordinate from map space. - * + * * @param y * @param zoom * @return */ - public double cYToLat(int y, int zoom); + double cYToLat(int y, int zoom); /** - * "Walks" westerly a certain distance on a latitude and returns the - * "mileage" in map space pixels. The distance is specified as angular - * distance, therefore this method works with all length unit systems (e.g. - * metric, imperial, ...). - * + * "Walks" westerly a certain distance on a latitude and returns the "mileage" + * in map space pixels. The distance is specified as angular distance, therefore + * this method works with all length unit systems (e.g. metric, imperial, ...). + * * @param startX * x-coordinate of start point * @param y @@ -97,12 +92,12 @@ public interface MapSpace { * 3956.6miles) * @return "mileage" in number of pixels */ - public int moveOnLatitude(int startX, int y, int zoom, double angularDist); + int moveOnLatitude(int startX, int y, int zoom, double angularDist); /** * Calculates the distance between two points that are laying on the same * latitude / y-coordinate. - * + * * @param zoom * @param y * y-coordinate specifying the latitude @@ -111,12 +106,18 @@ public interface MapSpace { * @return angular distance angular distance: distance / earth radius (e.g. * 6367.5km or 3956.6miles) */ - public double horizontalDistance(int zoom, int y, int xDist); + double horizontalDistance(int zoom, int y, int xDist); - public Point changeZoom(Point pixelCoordinate, int oldZoom, int newZoom); + double distance(double lat1, double lon1, double lat2, double lon2); - public int xChangeZoom(int x, int oldZoom, int newZoom); + Point changeZoom(Point pixelCoordinate, int oldZoom, int newZoom); - public int yChangeZoom(int y, int oldZoom, int newZoom); + int xChangeZoom(int x, int oldZoom, int newZoom); + + int yChangeZoom(int y, int oldZoom, int newZoom); + + enum ProjectionCategory { + SPHERE, ELLIPSOID, GEOID + } } diff --git a/mobac/src/main/java/mobac/program/interfaces/RefreshableMapSource.java b/mobac/src/main/java/mobac/program/interfaces/RefreshableMapSource.java new file mode 100644 index 0000000..4c29092 --- /dev/null +++ b/mobac/src/main/java/mobac/program/interfaces/RefreshableMapSource.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.interfaces; + +import mobac.gui.mapview.PreviewMap; + +public interface RefreshableMapSource { + + /** + * Called whenever {@link PreviewMap#refreshMap()} is executed + */ + void refresh(); +} diff --git a/mobac/src/main/java/mobac/program/interfaces/ReloadableMapSource.java b/mobac/src/main/java/mobac/program/interfaces/ReloadableMapSource.java new file mode 100644 index 0000000..5e328be --- /dev/null +++ b/mobac/src/main/java/mobac/program/interfaces/ReloadableMapSource.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) MOBAC developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + ******************************************************************************/ +package mobac.program.interfaces; + +import mobac.exceptions.MapSourceInitializationException; + +/** + * Marks {@link MapSource} implementations that can be reloaded (e.g. a custom + * XML based map source) + */ +public interface ReloadableMapSource { + + void applyChangesFrom(MapSourceType reloadedMapSource) throws MapSourceInitializationException; +} diff --git a/src/main/java/mobac/program/interfaces/RequiresSQLite.java b/mobac/src/main/java/mobac/program/interfaces/RequiresSQLite.java similarity index 81% rename from src/main/java/mobac/program/interfaces/RequiresSQLite.java rename to mobac/src/main/java/mobac/program/interfaces/RequiresSQLite.java index d07b624..1df4010 100644 --- a/src/main/java/mobac/program/interfaces/RequiresSQLite.java +++ b/mobac/src/main/java/mobac/program/interfaces/RequiresSQLite.java @@ -1,28 +1,31 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; /** - * Marker-Interface which has to implemented by all atlas creator classes which require the SQLite libraries. + * Marker-Interface which has to implemented by all atlas creator classes which + * require the SQLite libraries. */ public interface RequiresSQLite { + int MAX_BATCH_SIZE = 1000; + /** * Accumulate tiles in batch process until 20MB of heap are remaining */ - public static final long HEAP_MIN = 20 * 1024 * 1024; + long HEAP_MIN = 20 * 1024 * 1024; } diff --git a/src/main/java/mobac/program/interfaces/TileFilter.java b/mobac/src/main/java/mobac/program/interfaces/TileFilter.java similarity index 78% rename from src/main/java/mobac/program/interfaces/TileFilter.java rename to mobac/src/main/java/mobac/program/interfaces/TileFilter.java index 152a4d4..53dacb6 100644 --- a/src/main/java/mobac/program/interfaces/TileFilter.java +++ b/mobac/src/main/java/mobac/program/interfaces/TileFilter.java @@ -1,37 +1,41 @@ /******************************************************************************* * Copyright (c) MOBAC developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . ******************************************************************************/ package mobac.program.interfaces; /** - * Basic interface that allows to filter tiles based on their position and zoom level in the map. + * Basic interface that allows to filter tiles based on their position and zoom + * level in the map. */ public interface TileFilter { /** * Tests if the tile specified by the parameters should be included or excluded - * + * * @param x * @param y * @param zoom * @param mapSource - * @return