Prefix path for FXML files in TornadoFX - javafx

Is there a way to provide a path for FXML files, used by TornadoFX, with using its convention by fxml()?
Normally, TornadoFX conventionally tries to locate FXML resources in src/main/resources, however, our application is large and this might now be the best idea. In our case, we would like to maintain the files in a subdirectory, i.e. src/main/resources/fxml.
We would like to set it up during application startup. Is this possible?

I've added an FXML locator function to the framework so that you can override this to change the resource location. The declaration and default implementation looks like this:
var fxmlLocator: (component: UIComponent, location: String?) -> URL = { component, location ->
val targetLocation = location ?: component.javaClass.simpleName + ".fxml"
requireNotNull(component.resources.url(targetLocation)) { "FXML not found for ${component.javaClass} in $targetLocation" }
}
You can override this in app.init() for example, like this:
FX.fxmlLocator = { component, _ ->
val targetLocation = "/fxml/${component.javaClass.simpleName}.fxml"
requireNotNull(component.resources.url(targetLocation)) { "FXML not found for ${component.javaClass} in $targetLocation" }
}
However, if you go this route you must pay attention to your class names, as the same class name in different packages would look for the same resource in /fxml. Alternatively, change the implementation to observe the package names as well.
I'm committing the feature now, you can try it out tomorrow using the latest snapshot release from sonatype.

Related

CamelCase property names with NJsonSchema C# CodeGeneration

does anybody know a way to configure NJsonSchema to use CamelCase property naming durching code generation? I've a JSON schema with property names like message_id which lead to C# property name 'Message_id' where i.e. 'MessageId' whould be a more C#-like way.
With an attribute like '[JsonProperty("message_id"]' it would be no problem to specified the connection between the different names.
So, you asked about code generation. I was having trouble with the schema it generated not matching what was getting sent to my Angular app. So, while this isn't exactly what you were looking for, perhaps it helps you find an answer (maybe?).
To generate the schema with the camel case property names, I'm setting the Default Property Name Handling to CamelCase, but this is using the deprecated call to set these settings directly. There should be some way to use the SerializerSettings directly, but I wasn't quite able to make that work. This isn't production code for me, so it will do.
internal class SchemaFileBuilder<T>
{
public static void CreateSchemaFile()
{
CreateSchemaFile(typeof(T).Name);
}
public static void CreateSchemaFile(string fileName)
{
JsonSchemaGeneratorSettings settings = new JsonSchemaGeneratorSettings();
settings.DefaultPropertyNameHandling = PropertyNameHandling.CamelCase;
var schema = NJsonSchema.JsonSchema.FromType<T>(settings);
var json = schema.ToJson();
Directory.CreateDirectory("Schemas");
File.WriteAllText($"Schemas\\{fileName}.schema.json", json);
}
}
I set this up as a generic function so I could pass multiple schemas in to either createSchemaFile functions. Here's are some example calls which would generate a Person.schema.json file and a Persons.schema.json file:
SchemaFileBuilder<Person>.CreateSchemaFile();
SchemaFileBuilder<Dictionary<string, Person>>.CreateSchemaFile("Persons");

How can I add .NET namespace information in DocFX

The title says it all ...
In Sandcastle Help File Builder we added the NamespaceDoc class to each namespace to create namespace documentation.
How do we to the same using DocFX?
Here's how I did it:
In the root folder of your documentation project, add a folder named namespaces.
Update your docfx.json file to include markup files added to the namespaces folder. You need to update the overwrite property in the build section. It will look something like this:
"overwrite": [
{
"files": [
"apidoc/**.md",
"namespaces/**.md"
],
"exclude": [
"obj/**",
"_site/**"
]
}
],
Create a markdown file in the namespaces folder for every namespace you want to add documentation to. It is probably best to name these files the same as the namespace.
The files should have a YAML header with a UID that matches the namespace's name. The summary: *content line tells docfx to overwrite the summary of the namespace with the contents of this file.
The rest of the page is standard markdown that will become the namespace's summary. For example:
---
uid: My.Groovy.Namespace
summary: *content
---
The My.Groovy.Namespace namespace contains a bunch of classes and interfaces.
There isn't a way to add it directly in source code. You can use overwrite files to add summary for namespace type.
I'm probably extremely late to this question, but i faced a similar problem and the solution i found invovles modifying docfx from source and adding helping classes, much like Sandcastle's solution.
Disclamer:
I do not claim that the solution i'm showcasing is programmatically
stable, safe or even correct. I do not claim that this solution will
work in any scenario or for any use. I only verify that, for me, it
worked perfectly fine, even though i recongize it's just a fast-put-up
workaround.
Steps :
I downloaded the source code of docfx from their github's releases page (2.59.2, as of today)
After extracting the solution, I opened the file docfx-2.59.2\src\Microsoft.DocAsCode.Metadata.ManagedReference\ExtractMetadataWorker.cs
The class implemented within this file contains a method named GetMetadataFromProjectLevelCache that, at some point, extracts the metadata
from the referenced project in a tree form.
private Tuple<MetadataItem, bool> GetMetadataFromProjectLevelCache(IBuildController controller, IInputParameters key){
// [...]
projectMetadata = controller.ExtractMetadata(key); // THIS line
// [...]
}
After this line, I appended the following line containing a method which I also had to implement.
private Tuple<MetadataItem, bool> GetMetadataFromProjectLevelCache(IBuildController controller, IInputParameters key){
// [...]
projectMetadata = controller.ExtractMetadata(key);
ExtractNamespaceDocumentation(projectMetadata); // THIS line
// [...]
}
The implementation was the following:
private void ExtractNamespaceDocumentation(MetadataItem node)
{
// Terminal nodes are not of our interest in any case
// Even if it's a namespace, it does not contain documentation
if (node.Items is not { Count: > 0 }) return;
// If it is namespace
if (node.Type == MemberType.Namespace)
{
// Get (if any), the child that is class and is named "_NamespaceDoc"
var doc = node.Items.FirstOrDefault(x =>
x.Type == MemberType.Class && x.Name.Split('.').Last() == "_NamespaceDoc");
// If we didn't found such class, the namespace does not contain documentation.
// Leave and don't go further.
if (doc is null) return;
// Else, assign the class' Summary and remarks to the Namespace and remove the class from the tree.
node.Summary = doc.Summary;
node.Remarks = doc.Remarks;
node.Items.Remove(doc);
// job finished for this namespace, we do not want to go further down the tree.
return;
}
// For non-namespace intermediate nodes (IE assembly nodes), visit the children.
foreach (var child in node.Items) ExtractNamespaceDocumentation(child);
}
Lastly, I compiled the solution and, by using the newly created docfx.exe located at docfx-2.59.2\src\docfx\bin\Debug\net472, i was able to detect all classes named _NamespaceDoc and use their <summary> tags to fill the namespaces they resided.
For the record, i decided to create a new .cs file at the root of my project to contain all _NamespaceDoc classes, so it would be easier for me to disable the whole file when i want to release the project. This file looked like this:
namespace RootNamespace
{
/// <summary>
/// Documentation for the Root Namespace
/// </summary>
public static class _NamespaceDoc { }
}
namespace RootNamespace.SubFolder
{
/// <summary>
/// Documentation for the Root Namespace's `SubFolder` Sub-Namespace.
/// </summary>
public static class _NamespaceDoc { }
}
// [...]
Hopefully, this may help other fellows seaking for such solution, or even the docfx devs and contributors to implement this feature more reliably.
Update:
For more info about this approach, I've started a discussion
on docfx's github repository

Symfony 2 get Sonata media file path in Entity class

When implementing a __clone() method in media entity, I need to get the absolute path of a file to be able to make a copy of the file itself. I've been searching for a long time and I have not found any documentation to get this. Any ideas?
Here it is the __clone() method where I need the file path:
// Norwalk\StoreBundle\Entity\ProductHasMedia
public function __clone() {
if ($this->id) {
$this->media = clone $this->media;
$this->media->setProviderReference('clone_'.$this->media->getProviderReference());
$this->media->setName('clone_'.$this->media->getName());
$providerMeta = array('filename' => $this->media->getName());
$this->media->setProviderMetadata($providerMeta);
// Clone the physical image file too
$fs = new Filesystem();
$fs->copy( "original_image_path/".$this->media->getName(), "original_image_path/"."clone_".$this->media->getName());
}
}
I don't think it is possible without giving the Entity class to much responsibilities since you can't tell the absolute path name without having some services ('sonata.media.manager.media', 'sonata.media.provider.image' or 'sonata.media.twig.extension')..
The proper way to go is to build a clone function into an controller. The controller can have all the magic (services and entitymanagers) to do the cloning for you.
See this stackoverflow question for an example.

Access objects instantiated in Flex app's MXML file in other AS classes

I've got an object declared and instantiated in my Flex application's singular MXML file:
public var CDN:CDNClass = new CDNClass;
I would like to access this same CDN object (and its public methods and properties) in another class declared in a separate .as file as such:
package my.vp
{
import my.media.CDNClass;
public class SyncConnectorManager
{
private function syncMessageReceived(p_evt:SyncSwfEvent):void
{
switch (p_evt.data.msgNm)
{
case "startStream" :
// Play a stream
CDN.parsePlayList(p_evt.data.msgVal);
break;
But when I try to access the public method parsePlayList in the CDN object in a method in the class defined in the .as file, I get the following error:
Access of undefined property CDN
The reason I want to do this is to break up the logic of my application into multiple AS files and have minimal MXML files, probably only one.
Thanks - any help is much appreciated. Perhaps my OOD/OOP thinking is not correct here?
IT depends on your class architecture. For your code to work, the CDNClass instance must be defined and implemented inside your SyncConnectorManager.
Generally, you can always call down into components, but should never call up
One option is to pass the instance ofCDNClass to a variable inside SyncConnectorManager. Add this variable to your SyncConnectionManager class:
public var CDN:CDNClass = new CDNClass;
And at some point do this:
syncConnectorManagerInstance.CDN = CDN;
That way both classes will have access to the same CDN instance and can call methods on it.
Yes, your OOP thinking is not correct here. You should take in mind differences between classes and instances. This line declares a filed in a current class and initiates it with an instance:
public var CDN:CDNClass = new CDNClass;
So current instance of your MXML class (you can think about it as usual AS class with some other notation) has public field. To operate with CDN instance you need something from the following:
Read the value of CDN (as far as it is public) from the instance of your MXML class. You need some reference to it for that.
The instance of your MXML class can have a reference to the instance of SyncConnectorManager and SyncConnectorManager should have a way to inject the value of CDN there. Something like:
Your class:
package my.vp
{
import my.media.CDNClass;
public class SyncConnectorManager
{
private var CDN:CDNClass;
public function SyncConnectorManager(CDN:CDNClass)
{
this.CDN = CDN;
}
private function syncMessageReceived(p_evt:SyncSwfEvent):void
{
switch (p_evt.data.msgNm)
{
case "startStream" :
// Play a stream
CDN.parsePlayList(p_evt.data.msgVal);
break;
In your case SyncConnectorManager class hasn't CDN declared (the problem of the compiler error you mentioned) and instantiated (the problem of NPE even if you just declare field).
As the bottom line I can suggest you to follow ActionScript naming and coding conventions to talk other people and team members about your code :)

Are there Decorators / Macros / Annotations in AS 3?

I'm looking for the equivalent of Python decorators / Lisp macros / Java annotations (yes, I know that these are not necessarily equivalent themselves) in Actionscript. Tools that provide similar features would also be great (I'm using the Flex Builder plugin for Eclipse on Linux).
I'm writing a Flex application and here's what I want to accomplish:
I have encapsulated various sets of remote functionality in separate classes (this is sometimes called "Messaging Gateways" or "Remote Proxies"), where each method mirrors a method on the server, like so:
class UserManagementService extends MyHttpService {
//...
private final _urlBase:String = "http://example.com/services/users"
//...
public function usrGet(ix:int):User
{
url = urlBase + "/get";
mp:Dictionary = new Dictionary();
mp["ix"] = ix;
result:User = this._service.varSend(url, this.sEncodeParams(mp), Class("User"));
return result;
}
//...
}
Since I have the parameters and the return type of the remote function already in the function declaration, it would be nice to just add the URL suffix, like this (Python-inspired pseudocode):
#remotify("/get")
public function usrGet(ix:int):User { }
Now, wouldn't that be neat? ;-)
You can add what is called "metadata" in ActionScript like so:
[Remotify(prop="value")]
More information is here:
http://www.adobe.com/cfusion/communityengine/index.cfm?event=showdetails&productId=2&postId=11907

Resources