Reloading custom tool from svg markup string - autodesk-forge

I'm using the Markup Core extension and have created a custom tool with Edit Mode etc. The tool seems to be working fine on first adding to the canvas, dragging, resizing and on clicking save, I can see my new DotMarkup in the markups array.
However, when calling generateData and saving an svg string, an attempting to load the data onto a new layer using loadMarkups(svg, layerName) the custom markup is shown on screen but is unclickable, the markup is not visible in the markups arrays (on the editor, or in the svg markups array).
Any help appreciated

I've recently been looking into this as well, and unfortunately it turns out that exporting and re-importing custom markups is not yet supported by the MarkupsCore extension. If you look at the extension code and search for createMarkupFromSVG, you'll notice towards the end of the function that it's just a long switch with the built-in markup types. So, while your custom SVG is loaded, it's not considered a "markup SVG". To work around this issue you would probably have to parse the SVG string yourself and set the internal state of of the extension (such as this.markups) manually.

Related

Property '_popup' does not exist on type 'Marker<any>'

So, I am building a map using angular and leaflet. One of the things that I use is leaflet.markercluster. When i click on the cluster I want the popup content of a random marker of a cluster to be written somewhere. To access the popup content of some random cluster I did this:
cluster.getAllChildMarkers()[0]._popup._content
and got an error: Property '_popup' does not exist on type 'Marker'.
But the thing is, if I do ng serve first time it failes to compile, but if I change anything and save all it compiles sucessfully with the errors and I can see the content of the popup.
Also, if I do console.log(cluster.getAllChildMarkers()[0]) and I inspect element on webpage I get the regular console log of a marker with latlng andall other atributtes, including _popup.
Does anybody know why does typescript/vscode log an error, but html console sees it normally?
Because TypeScript is more strict than JavaScript, it warns you of potential issues that may actually work just fine once transpiled in JS.
In this specific case, this is simply due to the pseudo private properties ("_popup" follows the usual JS libraries convention of using an underscore _ prefix to denote pseudo private members) not being declared on the TS types of Leaflet, since you are not expected to use them.
But of course this is still technically valid in JS, so you can tell the TS compiler "I know what I am doing" by using the //#ts-ignore comment directive just above that line.
Or longer but much better, since you can remain under TS watch: use actual Leaflet API to achieve what you are doing:
getPopup() method
getContent() method
cluster.getAllChildMarkers()[0].getPopup()?.getContent()

Rendering with Chromium direct to my own 'canvas' (e.g. GDI+)

First, a quick description of the end-goal:
I'm building a cross-platform, .NET Core-based, printing app. This app will be able to print all sorts of file types with custom page settings, such as headers, footers, and margins. A key feature is it supports multiple-pages-up (e.g. a landscape sheet of paper with two portrait pages rendered side by side...called "2up").
Printing HTML is important not just because of printing HTML, but I want to use all the great HTML-based syntax-highlighting out there for source code (e.g. www.prismjs.com).
The app is basically done but for one major problem: I can't get the HTML to render well enough. So far I've implemented source code printing three ways:
1) As plain text with my own line-numbering and line-wrap engine. This works wonderfully for everything I can throw at it, but it does not support syntax highlighting.
2) Using Html-Renderer (https://github.com/ArthurHub/HTML-Renderer/issues) an OSS .NET-based Html Renderer. This implementation is the weakest because Html-Renderer's CSS support is really weak. It can't handle hardly anything prismjs or highlightjs' generate.
3) Usinglitehtml' (www.litehtml.com) via LiteHtmlSharp. This was very promising and I almost have it working with some major hacks, but litehtml also does not support key, modern, HTML/CSS features.
Neither Html-Renderer or litehtml support the CSS page-break-before feature that, when combined with media print would let me ensure lines are not split between pages.
What I really want to use is the Chromium rendering engine. litehtml provides a fantastic API for this sort of problem: It calls me whenever it needs to render, and I draw (text, table borders, images, etc...) using GDI+. My dream is to find something in Chromium (CEF, Puppeteer, ???) that provides a similar API.
Or, an alternative, an API that will let me pass in a GDI+ Graphics (or HDC) and the renderer will render to that surface.
With Html-Renderer I measure calculate # pages like this.
SizeF size = HtmlRender.MeasureGdiPlus(g, html, containingSheet.GetPageWidth());
int numPages = (int)(size.Height / containingSheet.GetPageHeight());
My page rendering code (e.g. OnPaint) looks like this:
SizeF size = new SizeF(containingSheet.GetPageWidth(), containingSheet.GetPageHeight());
HtmlRender.RenderGdiPlus(g, html, PointF(0, 0), size );
With htmllite the OnPaint code looks like this:
// Set the clip such that any extraLines are clipped off bottom
g.SetClip(new Rectangle(0, 0, (int)Math.Round(PageSize.Width), (int)Math.Round(PageSize.Height - remainingPartialLineHeight)));
LiteHtmlSize size = new LiteHtmlSize(Math.Round(PageSize.Width), Math.Ceiling(PageSize.Height));
litehtml.Document.Draw((int)-0, (int)-yPos, new position {
x = 0,
y = 0,
width = (int)size.Width,
height = (int)size.Height
});
And in this case the call to litehtml.Document.Draw causes a bunch of callbacks into my app that I process using the same Graphics the OnPaint is called with.
Most discussions of CEF and Chromium point to ScreenshotAsync etc... which will not do because I need to be rendering to a PRINTERS HDC (or GDI+) and blitting bitmaps will loose quality.
I have poured over the Chromium source and I cannot find the obvious way to say to CEF/Chromium "render page 1 (defined as Height/Width) to this GDI+ Graphics object" then "render page 2..." etc... The printing support (and how pdfium is integrated come close!).
Chromium issue 311308 indicates I'm hosed until this work gets picked up again.
Note: I have full access to nodejs w/in my app. I have built a dotnet/nodejs bridge, which is how I convert the raw text file of a source code file to richly formatted, line-numbered, syntax-highlighted html via prismjs. This means I could easily use puppeteer/Headless Chrome if I could just figure out the right APIs.
Does anyone have a suggestion that might help? I'm willing to contribute to Chromium if it's not major heart surgery.

How to restore viewer state directly from MarkupEdit or MarkupView mode?

With reference of https://forge.autodesk.com/cloud_and_mobile/2016/02/playing-with-the-new-view-data-markup-api.html, I am implementing 2D markup feature in forge viewer.
I'm using Autodesk.Viewing.MarkupsCore library to draw annotations over model in forge viewer. For that I'm loading Autodesk.Viewing.MarkupsCore extension as _markupsExtension .
I tried drawing some markup annotation and saved viewer state. When I tried loading these previously drawn annotations, It failed to restore viewer state, but it was loading annotations data properly.
// To draw and save markup
viewer.loadExtension("Autodesk.Viewing.MarkupsCore").then(function(markupExt) {
_markupsExtension = markupExt;
_state = _markupsExtension.viewer.getState();
_markupsExtension.hide();
_markupsExtension.enterEditMode();
//From now on, while in EditMode, the user will be drawing text boxes
_data = _markupsExtension.generateData(); //Annotations data can be generated
_state = _markupsExtension.viewer.getState(); //to store viewer state information
_markupsExtension.leaveEditMode();
viewer.unloadExtension("Autodesk.Viewing.MarkupsCore"); //User can navigate within model
});
// To load previously drawn markup
viewer.loadExtension("Autodesk.Viewing.MarkupsCore").then(function(markupExt) {
_markupsExtension = markupExt;
_markupsExtension.leaveEditMode();
_markupsExtension.show();
_markupsExtension.viewer.restoreState(_state); //it fails to restore state
_markupsExtension.viewer.impl.invalidate(true);
_markupsExtension.loadMarkups(_data, 'aaa'); //loads markup data while keeping viewerstate unchanged.
});
Why does it fail to restore state while being in markup viewing mode?
What is difference between _markupsExtension.viewer.restoreState(_state) and viewer.restoreState(_state)
================================ EDITED =============================
Is there any way where I could stay within editing mode/viewing mode and change viewer's state?
I am saving all markups in a list view in different sessions or file per session (referring https://forge.autodesk.com/cloud_and_mobile/2016/02/playing-with-the-new-view-data-markup-api.html ).
e.g. 1) I moved model to the top and drawn arrow pointing to particular object and I saved it with name "MarkupA.json".
2) I moved model to front and zoomed it out so that it went far from camera. Then I drawn Square markup and stored it with name "MarkupB.json".
3) Then again I kept model to default iso (home) mode and drawn text annotation and saved it with name "MarkupC.json".
All these markups are listed in the UI panel like a tree. So when am clicking on any particular name, that markup and its model viewer state has to get restored without change in any markup mode.
I have checked this similar functionality in bim360. When I stored different markups in BIM360, it stored all markups in its database and small thumbnail screenshot appeared for its relevant markup card. I viewed all markups in markup panel or comment panel.
When I clicked on specific thumbnail, every markup appeared with appropriate stored viewer state.
I am trying to get similar functionality in forge viewer using new Markups core extension and customised its markup code to store states with markups. When I tried to load each markup, it seems like markup is getting loaded but its viewer state is not able to get restored neither in edit mode nor in viewing mode. I understood that restoring state is not possible if we are in markups mode. But what if I want to show the previously stored drawn markup on particular view?
The workaround which I tried to switch between markup is as follow,
On click of another markup -
a) leave viewing mode
b) restore model with stored state
c) enter viewing mode.
d) load its markup svg.
The issue with this is it is taking too much time taking too much time to reload markup with restored state.
Can you please tell me if we have any other workaround or approach to achieve loading and restoring markup and its viewer state synchronously?
Why does it fail to restore state while being in markup viewing mode?
When in markup mode the camera is locked so you will need to drop out of edit mode before restoring Viewer states and then go back.
What is difference between _markupsExtension.viewer.restoreState(_state) and viewer.restoreState(_state)
No difference as _markupsExtension.viewer is just a reference of the plugin to the master Viewer object

mxClient renders different shapes all as squares

Several weeks ago I have been asked to upgrade a web application based on a very old version of MXGraph library (version 2.4). The application integrated also the 'grapheditor' a sort of demo application evolved later in Diagramly
and then in Draw.io). Recently I completed the more problematic step, the transition from old "grapheditor" to Draw.io, so I am now able to open all the previous diagrams (saved as plain XML), modify and save them consistently.
Ok, this is the nice part. The bad side is the 'read-only' section of the application ,where the users can more or less, only view the graph.
This page is based on the mxClient.js that renders the graph described in the xml through this code:
var graph = new mxGraph(container);
var diagram = mxUtils.parseXml(xml);
var codec = new mxCodec(diagram);
codec.decode(diagram.documentElement, graph.getModel());
graph.fit();
Upgrading the MX library to the last version (3.9.10) the same code works but some shapes are not rendered properly, they appears as squares instead of
circles, ellipses, etc. The two following images are an example of this misbehavior
Graph in the draw.io:
Same graph rendered by mxClient:
After some tries I discovered that the old mxClient is able to render the same graph perfectly (as draw.io does) so I think there have to be something wrong (or missing) in my code or mxGraph installation/configuration.
As a temporary workaround I can keep in place the old version of mxGraph but obviously I'd like to use the new one.
Can someone give me an hint on this? Any help would be very appreciated.
The tape shape isn't part of core mxGraph, it's part of the GraphEditor example, in the additional shapes JavaScript.
If you look at the style of the ellipse, it's probably not the one in the core, most likely another one from Shapes.js.
Either pull in shapes.js, or use the viewer in draw.io.

How to view source code of canvas element

I am trying to access the source code inside the canvas tag. Is it possible to get source code inside canvas tag?
You cannot get the source code from canvas element . You need to check the javascript to see what's going on in the canvas . Canvas is similar to board where you can draw anything with javascript .
The canvas element is part of HTML5 and allows for dynamic, scriptable
rendering of 2D shapes and bitmap images. It is a low level,
procedural model that updates a bitmap and does not have a built-in
scene graph
If you use Chrome you're in luck. It has an experimental feature for inspecting Canvas elements. So you can actually profile the canvas element and see step by step each call, and see a shot of the output of that call.
In chrome type chrome://flags/ into the URL and once the page loads, find "Enable Developer Tools experiments". Close out of Chrome and once you load it back up, in the inspector you will find a new option under Profiles for "Capture Canvas Frame". Run that and it will output a list of every call performed.
I learned about this through twitter and the following link, enjoy.
http://www.html5rocks.com/en/tutorials/canvas/inspection/