Thursday, 16 January 2025

Announcing: mapguide-react-layout 0.14.10 and MapGuide Maestro 6.0m13

We start the new year with a double-header release of:

  • MapGuide Maestro 6.0m13
  • mapguide-react-layout 0.14.10
What prompted these new releases other than (it's long overdue)?

Namely, it is to do with a notification I received about the coming deprecation (and eventual shutdown) of the epsg.io service that both pieces of software use to do proj4 projection lookups for any given EPSG code. This service will shutdown in Feburary (next month) and transition over to the MapTiler coordinates API. This new API requires an API key to use their services.

In the context of these 2 projects, the API key requirement introduces too much friction.
  • If I take up the offer to use MapTiler, I have to register and bake my API key into both Maestro and mapguide-react-layout and am now responsible for API usage/monitoring under this key from users I have no control over. Last thing I want to deal with is bug reports from users because, let's say for example: proj4 lookup is broken because the API is no longer accessible for my API key due to quota exceeded. I just don't want to deal with such a scenario.
  • Which means the alternative is to change the code to the extent that users can "bring their own API key", taking such API key usage/monitoring concerns out of my hands. This too is also too much hassle. I just want to do EPSG code to proj4 lookups nothing more nothing less!
If I was building a bespoke/custom mapping application for a client with EPSG > proj4 lookup functionality, then this API key requirement would not have been an issue, but this is not the case here.

So in light of these concerns, instead of moving to MapTiler coordinates. Instead I have opted to use spatialreference.org to do EPSG -> proj4 lookups. No API keys are required there.

So since this was the main driver for needing to put out new releases of MapGuide Maestro and mapguide-react-layout, we might as well take this opportunity to lump in some other fixes and minor changes, which are detailed below.

mapguide-react-layout changes

(reworked) Stamen and (new) StadiaMaps support

Stamen tiled layer support was broken for some time since it was taken over by Stadia Maps. I had already taken care of this in the VSCode map preview extension which had the same problem. But for mapguide-react-layout, the fix was a bit different due to it not using the latest version of OpenLayers and it is too much work right now to update to the latest OpenLayers in mapguide-react-layout.

So what was done for mapguide-react-layout instead is to create these Stamen tile layers as XYZ layers  instead of using the (now broken for that OL release) Stamen tile source. This works because Stamen tiles are ultimately tilesets using the XYZ web mercator scheme. The only other changes is that a Stadia Maps API key is required. So if your appdef defines one or more Stamen tile layers and you didn't specify an API key, you'll get the same startup warning you get when you have Bing Maps layers and didn't specify a Bing Maps API key


But if you do provide a Stadia Maps API key, you'll get the Stamen layers you've seen before.


Since a Stadia Maps API key is now required, we've also added support for other tilesets provided by Stadia Maps, like:

Alidade Smooth


Alidade Smooth Dark


Alidade Satellite


Outdoors


So if you are loading your mapguide-react-layout viewer from a Flexible Layout document, where do you need to specify this new Stadia Maps API key?

That's where the new release of MapGuide Maestro comes in to help!

MapGuide Maestro Changes

Stamen Maps (changed) and Stadia Maps (new) support

The Fusion Editor has reworked Stamen Maps support and added support for Stadia Maps


You'll notice that Stamen and Stadia Maps have 2 variants for every layer.
  • A specialized version
  • An XYZ layer variant ("... as XYZ")
What is the deal with this?

This was done so that if you are still authoring Flexible Layouts for Fusion instead of mapguide-react-layout, you can still view Stamen and Stadia Maps layers in Fusion through the existing XYZ layer support that is available in Fusion as demonstrated in the screenshot below, using the Stadia Maps alidade_smooth_dark tileset + API key.


So depending on the context:

If you are authoring a Flexible Layout for Fusion, choose the "... as XYZ" version and enter the Stadia Maps API key when prompted.

Otherwise, if you are authoring a Flexible Layout for mapguide-react-layout, choose the specialized version and enter the Stadia Maps API key in the provided field


This release of mapguide-react-layout will read the Stadia Maps API key from this new setting in the Flexible Layout when initializing with Stamen and Stadia Maps tile layers.

Using spatialreference.org for EPSG > proj4 lookups

As stated above, the projection management dialog of the Fusion Editor now uses spatialreference.org for resolving proj4 strings from EPSG codes


Other changes

  • WMS Feature Source Editor: Improved the responsiveness and usability of the Advanced Configuration Dialog
  • You can finally copy (ctrl-c) content in the IronPython console!!! You can now truly iterate on automation scripts by finally being able to copy the snippets of working Python code you just entered and eval-ed.

Download

Wednesday, 13 November 2024

Announcing: mapguide-rest 1.0 RC6.1

I've taken a momentary break from our (admittedly) glacial pace of MapGuide development to put out another release of mapguide-rest 

This release includes the following changes:

  • Fix missing reverse routing on selection overview
  • Fix bad feature query preparation when querying against watermarked layers
  • Relax strict-typing on MgReaderToGeoJsonWriter::FeatureToGeoJson() so that it can work with MgPaginatedFeatureReader allowing pagination to work again
  • Added missing properties parameter to swagger defn for session-based feature selection route

We now return to regularly-scheduled programming of trying to get MapGuide Open Source 4.0 to the finish line.

As for mapguide-rest, I envision at least once more major RC *after* the final release of MapGuide Open Source 4.0 before finally wrapping things up on development work and pulling the trigger on the mapguide-rest 1.0 final release. Enough of this RC-after-RC business!

Friday, 18 October 2024

Announcing: vscode-map-preview 0.7.0

It has been brought to my attention that my vscode-map-preview extension now produces 401 responses for stamen map tiles, which has prompted me to put out a new release of this extension to better handle this situation.

This new release updates OpenLayers to 10.2.1 and now hides stamen tile layers from the base layer switcher if you don't have a Stadia Maps API key in your extension settings as this API key is now a requirement for viewing stamen tile layers.

Thursday, 15 August 2024

Announcing: MapGuide Open Source 4.0 Beta 2

This took way longer than expected, but the 2nd beta release of MapGuide Open Source is now available.

The main driver for this release is to update our various web tier components to their latest respective versions:

  • PHP 8.1.29
  • Apache httpd 2.4.62
  • Apache Tomcat 9.0.89
In addition to that, the Beta 2 release includes the following changes:

  • Installer
    • Newer libpq.dll (PostgreSQL 16.3) bundled with Windows installer
  • Server Tier
    • Fix instability on Linux due to criss-crossed resolution of sqlite3 and geos symbols to our shared libraries instead of the distro-provided versions
    • Repository admin tools have been momentarily pulled from this and future beta releases until the admin scripts have been updated and/or rewritten. As a workaround, use MapGuide Package files to backup/restore repository content
    • Removed immature MVT tile rendering support. If you want to produce Mapbox Vector Tiles, use any tool from this list
  • Web Tier
    • Fix QUERYMAPFEATURES SelectionKey containing a newline char, breaking client-side reconciliation of selected features
    • More PHP8 compatibility fixes in PHP AJAX Viewer
    • Fix bad instanceof exception checks in PHP AJAX Viewer
    • More PHP8 compatibility fixes in Site Administrator
    • Buffer overflow fixes in WMS/WFS service layer
    • New optional --bind-to parameter for MgDevHttpServer
  • InstantSetup
    • Fix crash if no setup log path specified when configuring
  • Samples
    • Fix bad extents in SheboyganXYZ tileset
So with this release out the door, what is next? Well unfortunately, there is still lots of work to do on the API binding and API documentation front, and so in the interests of not having you wait another year between releases, I am now adopting the policy of "however many beta/rc releases required" which implies more frequent beta/rc releases. As one of the major remaining items is completed and/or newer versions of any of our web tier components are available, that will be the trigger for a new beta/rc release.

Download

Note: Trac is a bit flaky right now, so the release notes page may not display. If that happens just retry with browser refreshes. Failing that, you can find all the necessary download links in my release announcement email

Thursday, 21 March 2024

Avalonia UI Test Drive

As the title implies, this blog post is about my experience test driving Avalonia UI.

So why am I doing this?

I've been getting growing questions lately about whether MapGuide Maestro works on Linux via Mono

Sadly I no longer emphasize anything regarding Mono compatibility because.

  • WinForms support (in legacy .net Framework 4.x) on Mono is pretty much a hack.
  • And since we've moved away from legacy .net Framework to .net 6.0, the combination of WinForms + .net 6.0 is probably an unsupported combination (you don't use Mono to run .net core/5.0+ applications, you use Microsoft's official SDK/runtime). I'm also not too keen to waste time and resources to test and find out.
The best and practical approach for a multi-platform MapGuide Maestro would be to at a minimum to rewrite the UI in a library/framework where support on non-Windows platforms is a first-class citizen.

And in terms of .net multi-platform UI frameworks, there's only one logical choice: Avalonia UI

While it is not in my immediate plans to rewrite MapGuide Maestro's UI in Avalonia, I wanted to at least explore the feasibility of building such a UI even if all the actual functionality is mocked up, just to see how easy or difficult the whole process is.

Hence the motivation for this post.

So why Avalonia?

Avalonia is effectively the "spiritual successor" to WPF, and adopts most of the same patterns and practices when building UIs for Avalonia.

I had first heard about Avalonia when it was formerly known as Perspex and at the time, from the screenshots of example Perspex applications on Windows and non-Windows platforms, it was clear at that point in time the range of possible applications one can build with Perspex was quite limited and building an application like Maestro on top of Perspex was not feasible.

Just recently, I had heard about the framework now known as Avalonia again and this time round there was a lot more positive buzz around it, so I gave it another look and was much more impressed at its capabilities and richer suite of UI controls to build applications with.

Our objective 

My objective with this Avalonia learning exercise was to build a minimal multi-document interface skeleton application, mimicking the primary functionality (UI-wise) of MapGuide Maestro.

  • Being able to present a login UI to connect to a MapGuide Server
  • Present MapGuide Server resources in a tree view
  • Open resources in a region of tabbed editor panels and being able to close them.
This is a crude wireframe of the kind of UI I wanted to build.
If this kind of UI looks familiar, yes it's basically the UI for tools like:
MapGuide Maestro is an IDE-like application (in terms of UI), so my first instinct is to look for a Visual Studio like docking library for Avalonia. However, I've been using Visual Studio Code more often than full Visual Studio as my daily driver for coding and the VSCode UI has become my default UI that I want to replicate for any IDE-like application with a multi-document interface.

The benefit of such a UI, is that it doesn't require an explicit VS-style window docking control like I have for the current WinForms-based MapGuide Maestro. I can already see the controls needed to build such a UI

Any UI toolkit worth its salt should to able to provide these basic controls.

This is a proof-of-concept, so we won't be using the existing Maestro API to talk to actual MapGuide Servers. Instead such functionality will be mocked up for this application. The main purpose of this exercise is to see if Avalonia provides enough of the base UI elements to build a hypothetical version of MapGuide Maestro on top of.

It turns out this exercise was fraught with several challenges

Challenge #1: Getting familiar with Avalonia concepts

The first challenge was simply getting familiar with Avalonia concepts. Being someone who did .net desktop app development primarily in Windows Forms, I skipped over WPF, and its XAML-based variants/successors like Silverlight, Xamarin Forms, UWP, and MAUI, and Avalonia being a "spiritual successor" to WPF meant that I didn't have a potential conceptual head start on Avalonia that one might have if they already had experience with WPF and its XAML-based derivatives.

However, I was familiar with the MVVM pattern and data-binding, which is used heavily in Avalonia. I already had experience in knockout.js building/maintaining some of our web apps in my day job, and these concepts learned from knockout.js mostly translate cleanly 1:1 to Avalonia.

The other Avalonia concepts I'll have to figure out as we go along.

Challenge #2: WebAssembly (WASM) support

Before I begin, I must take the MapGuide-knowledgable readers of this post back in time, way back to when MapGuide Open Source 1.0 was released.

Do you remember how this new (at the time), re-invented version of MapGuide was released, but the only authoring option at the time was to buy a license of Autodesk MapGuide Studio? Not a pretty look if you are offering a free and open source web map GIS server, but the authoring tools are not?

Some members of the MapGuide community were aware of this glaring discrepancy and created a web-based equivalent of MapGuide Studio called Web Studio built fully with HTML/JS/CSS. Unfortunately, Web Studio was really bare-bones in terms of authoring capabilities and the code being written in the pre-historic era of javascript (this was circa 2006-2007) which did not make it conductive to external contribution. React, TypeScript and friends weren't around then, so trying to enhance Web Studio with new features was extremely challenging. I once tried to add at least a generic XML text editor fallback for Web Studio so you had something to edit various resources where Web Studio did not provide a dedicated editor UI for, but alas this was just too challenging for me and I gave up on such an idea.

But eventually another user of the MapGuide community solved this problem more directly by developing and releasing a v1.0 of a windows .net desktop application that you all know as MapGuide Maestro. As an aside, I am not the original author of MapGuide Maestro in case you're wondering, I merely took over development and maintenance of Maestro from the 2.1 release onwards.

Anyways, back to the topic at hand, when I created the new Avalonia application with the provided project template, I was most surprised to see that the generated solution came with a project that compiled to WebAssembly (WASM) that was ready to run in your web browser!

This was a mind-blowing revelation for me from a conceptual standpoint. It means our hypothetical MapGuide Maestro built on Avalonia could not only exist as a regular desktop application, but the WASM build of this application could be dropped in the the wwwroot of a MapGuide Web tier installation and you would now have a modern version of Web Studio, but much more powerful and capable, because it is just MapGuide Maestro ... now in your web browser!

Since our starter project template includes a functioning WASM browser target. I now had a strong incentive to keep this target active and working, because the prospect of being able to run MapGuide Maestro in a web browser is a very tempting proposition. Therefore, the choice of libraries and APIs I use is constrained by my new requirement of being able to work in a browser/WASM environment.

For example, I originally wanted to use MVVMDialogs to simplify working with dialogs (Maestro has lots of dialogs, so I figure such a library could be useful), but I couldn't get this library to work in a WASM environment with some of my testing dialogs, so this was a no-go. Since this was just a proof-of-concept, there wasn't a need to have working dialog system, but it does mean if this were to go beyond a proof-of-concept and into an actual application where we will inevitably have to present a dialog of some sort, I'd have to come with a paradigm that can work in both desktop and browsers.

Another problem with this WASM target is that I can't seem to debug it in Visual Studio. You can launch the WASM target in the debugger and spawn a new browser window to launch your app, but any breakpoints you stick in your C# code are not being hit. I'm not sure if this a shortcoming or a broken feature, but it is somewhat concerning if we were to go full steam ahead with support WASM as a compilation/deployment target.

Challenge #3: "Large scale" MVVM

Although I already knew the MVVM pattern from knockout.js, my scope of usage was mostly limited to using knockout.js to building "islands" of interactive client-side content on primarily server-generated web pages. So I didn't really have an idea of how to apply such a pattern on a full blown Single Page Application (SPA), which is pretty much what we're trying to achieve (conceptually) in Avalonia. By the time I was building SPAs proper, I had moved on the popular stuff like React, which is how I gained the knowledge needed to build a modern replacement map viewer for MapGuide and my usage of knockout.js fell by the wayside as a result, so I never figured out the answer for how to do large scale MVVM.

The main problem was that in a large scale MVVM, how do view models communicate with each other without a tight parent-child coupling?

I deduced that for starters, we definitely need to use dependency injection. Various view models will need to access different services and if we had a root view model with explicit nested child view models (each with their own service requirements), it would be an absolute pain to have to setup these various view models. Using a DI container means we can offload this concern to it and we can focus on just asking the DI container for a particular view model and it will setup all the required services for it for us provided we register everything properly with the DI container.

For better WASM support, I wanted a dependency injection container that is not driven by reflection to make the code more friendlier to app trimming. We want to be able to app trim on publish so that we can eliminate unused code and reduce the final binary size. This is most desirable for the WASM target as app trimming means smaller binaries, which means smaller payloads to download in a web browser. StrongInject was chosen for this reason as it was a "compile-time" DI container that can verify all your dependencies are registered properly before running the application through the magic of source generators, generating all the necessary registration and validation code for you.

Finally, to be able to communicate between view models without necessary parent-child coupling, the messenger facility of the MVVM toolkit can be used. With this messenger facility, we simply:
  • Have select view models be recipients of certain messages
  • Have our application services (that various view model commands call) send these messages.
  • Relevant recipients get notified and update themselves (and their bound UIs) accordingly as a result.
I don't know if this is the proper usage of MVVM pattern in a "large scale" application, but it makes sense internally in my mind.

Challenge #4: TabControl binding of heterogenous/polymorphic content

Our proof-of-concept app has a main tab region where tabs of various document content are shown. I figured out easily that their TabControl component is supposed to be data-bound to an observable collection of view models, but what really stumped me was how bind this control to an observable collection of polymorphic editor view models?

The reason is because the tab content we want to show is not homogenous. One open editor tab could be for a layer, one for a map, one for a feature source, etc, etc. So we need to be able to show different tabs on the same tab control. 

Avalonia documentation is pretty scant on this topic. All examples I found assume homogenous series of tab content, which is not our case.

Just for laughs, since AI has been hyped for soon taking away everyone's jobs (even us devs), I figured I'd ask huggingface chat (as a guest), how would you solve this problem?


Unfortunately, the provided code sample does not work out of the box. It clearly assumed Avalonia = WPF and gave me a WPF-based solution. The giveaway was the Avalonia TabControl does not have an ItemTemplateSelector, but the WPF TabControl does.

But Avalonia sharing many conceptual similarities with WPF meant that although the answer provided wasn't correct, parts of the answer were applicable and did lead me down to further avenues of inquiry and eventually I found the solution: It was to define a data template for every possible derived tab view model class in the same UserControl where the TabControl was specified.

Final challenge: Avalonia VS designer

This wasn't so much a challenge, rather an annoyance. The Avalonia designer in Visual Studio has some teething issues
  • Intellisense/autocomplete is somewhat flaky when writing binding expressions and when you're doing a lot of data-binding, having the editor giving you and incomplete or outdated list of properties you can bind to becomes annoying. A full project build generally fixes this, but it is annoying having to do this every time I add new observable properties or commands to an existing view model class.
  • It's also not rename-aware, so observable property or command renames will result in stale binding expressions, causing havoc with the designer and have to be manually fixed up in the XAML. Choose your observable property names wisely I suppose, because renaming them afterwards is painful.

The end result and overall thoughts

A week later from that post, after addressing and/or navigating around these various challenges, we have a functional skeleton application!





And if these screenshots don't convince you, thanks to being able to deploy as a WASM target, I deployed a copy to GitHub pages, so you can see this app for yourself right in your WASM-enabled web browser!


The source code for this app can be found here. One day this may form the basis of a new (true) multi-platform version of MapGuide Maestro, but for now this lies as a potentially useful starting point for building a tabbed-multi-document editor application with Avalonia.

So what did I think of Avalonia from this little experiment? 
  • I like it mostly. My pre-existing experience on knockout.js helped greatly with picking up MVVM and data-binding. My initial prediction of a VSCode-style UI layout being buildable turned out to be true.
  • I like the default (project template provided) choice of MVVM Toolkit for applying the MVVM pattern. I like their heavy use of source generators to make adding new observable properties and commands to a view model being a simple case of tacking [ObservableProperty] on a field or tacking [RelayCommand] to a private method and having the source generator generate all of the boilerplate code for you (and it's a lot of boilerplate!).
  • The revelation that Avalonia has a WASM deployment target was both exciting and "cramping my style". It meant that certain libraries I wanted to use (eg. The MVVM dialogs library) could not be used and it wasn't clear what would work in a WASM browser environment and what wouldn't. Which leads to ...
  • Documentation is lacking in some areas. What really stumped me for a while was how do a TabControl bound to a collection of polymorphic or heterogenous tab view models. Their provided examples completely failed to tell me how to do this. I suppose if I came into this with existing WPF experience, this wouldn't have been so difficult as most of the concepts and patterns seem to be mostly transferable, but I happened to have skipped WPF and its bajillion XAML-based derivatives, so I didn't have this pre-existing knowledge to fall back on. Through perseverance and looking at the source code for many existing Avalonia applications on GitHub, I was finally able to determine that data templates was the solution.
So all-in-all, this was a fun and useful exercise and you get a useful starting point app from this effort!

Now I better get back onto this MapGuide/FDO work.

Monday, 18 December 2023

Minor change of plans

There will be a slight change of plans in the MapGuide Open Source 4.0 release timeline.

Namely, the next release will not be the Release Candidate, but rather a 2nd beta release.

The main driver behind this decision is because of my intention to remove the recently introduced support for Mapbox Vector Tiles. While I initially had high hopes with this implementation, additional testing with data outside of the example Sheboygan dataset has revealed rendering issues I do not have the capability to address. Rather than ship a half-baked implementation that may never bake fully, I'd rather bow out while we still can, remove this immature implementation, and leave MVT tile generation to dedicated external tools.

A 2nd beta release will also mean that the other changes I want to get in will also have some time to bake before the Release Candidate stage.

I am hoping the 2nd beta release will be out late January in the new year.

Monday, 4 December 2023

Announcing: mapguide-rest 1.0 RC6

6 years later, I have finally put out another release of mapguide-rest!

The reason for finally putting out a new release (besides being long overdue!), is that I needed a solid verification of the vanilla SWIG API binding work for MapGuide Open Source 4.0 and mapguide-rest was just the ideal project that touches almost every nook and cranny of the MapGuide API. So if mapguide-rest still works with the PHP binding in MapGuide Open Source 4.0, that is as good of an endorsement to the reliability and readiness of these bindings.

For this release of mapguide-rest, it is compatible with the version of PHP that comes with:

  • MapGuide Open Source 3.1.2 (PHP 5.6)
  • MapGuide Open Source 4.0 Beta 1 (PHP 8.1)
Besides being compatible with the upcoming MapGuide Open Source release (and the current stable one), this release also adds a new series of APIs to perform various geo-processing tasks. All of which are available to try out in the interactive swagger API reference.




Special thanks to Gordon Luckett and Scott Hamiester for assistance in internal testing of many internal builds of mapguide-rest that finally culminated in this long-overdue release.

Now that this is out of the way, it is back to MapGuide development proper and getting closer to the 4.0 release.