//layoutSpec helpers /// <summary> /// Serializes the layout specification to json stream and /// optionally replaces icon urls with image data as base64 encoded strings /// </summary> /// <returns></returns> private Stream ToJSONStream(LayoutSpecification spec, bool replaceIconURLWithData, IconResourceProvider iconProvider = null) { var ms = new MemoryStream(); var sw = new StreamWriter(ms); if (replaceIconURLWithData && iconProvider != null) { //foreach section update all nested children and nested includes, and root iconurls to image data. spec.sections.ForEach(section => { section.iconUrl = getBase64ImageString(section, iconProvider); section.EnumerateChildren().ToList().ForEach(child => child.iconUrl = getBase64ImageString(child, iconProvider)); section.EnumerateIncludes().ToList().ForEach(child => child.iconUrl = getBase64ImageString(child, iconProvider)); }); } var serializer = new JsonSerializer() { Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore }; serializer.Serialize(sw, spec); sw.Flush(); ms.Position = 0; return(ms); }
/// <summary> /// Updates the Libarary Layout spec to include layout for Steel nodes. /// The Steel layout spec is embeded as resource "LayoutSpecs.json". /// </summary> private static void UpdateLibraryLayoutSpec() { var customization = Model.DynamoModel.ExtensionManager.Service <ILibraryViewCustomization>(); if (customization == null) { return; } //Make sure to notify customization for application closing DynamoSteelApp.ShutdownHandler = () => customization.OnAppShutdown(); //Register the icon resource /*customization.RegisterResourceStream("/icons/Category.AdvanceSteel.svg", * GetResourceStream("Dynamo.Applications.Resources.Category.AdvanceSteel.svg"));*/ LayoutSpecification steelSpecs; using (Stream stream = GetResourceStream("Dynamo.Applications.Resources.LayoutSpecs.json")) { steelSpecs = LayoutSpecification.FromJSONStream(stream); } //The steelSpec should have only one section, add all its child elements to the customization var elements = steelSpecs.sections.First().childElements; customization.AddElements(elements); //add all the elements to default section }
/// <summary> /// Updates the Libarary Layout spec to include layout for Revit nodes. /// The Revit layout spec is embeded as resource "LayoutSpecs.json". /// </summary> private static void UpdateLibraryLayoutSpec() { //Get the library view customization service to update spec var customization = revitDynamoModel.ExtensionManager.Service <ILibraryViewCustomization>(); if (customization == null) { return; } if (shutdownHandler == null && extCommandData != null) { //Make sure to notify customization for application closing, so that //the CEF can be shutdown for clean Revit exit shutdownHandler = () => customization.OnAppShutdown(); extCommandData.Application.ApplicationClosing += (o, _) => shutdownHandler(); } //Register the icon resource customization.RegisterResourceStream("/icons/Category.Revit.svg", GetResourceStream("Dynamo.Applications.Resources.Category.Revit.svg")); //Read the revitspec from the resource stream LayoutSpecification revitspec; using (Stream stream = GetResourceStream("Dynamo.Applications.Resources.LayoutSpecs.json")) { revitspec = LayoutSpecification.FromJSONStream(stream); } //The revitspec should have only one section, add all its child elements to the customization var elements = revitspec.sections.First().childElements; customization.AddElements(elements); //add all the elements to default section }
/// <summary> /// Updates the Libarary Layout spec to include layout for Steel nodes. /// The Steel layout spec is embeded as resource "LayoutSpecs.json". /// </summary> private static void UpdateLibraryLayoutSpec() { //Get the library view customization service to update spec var customization = advanceSteelModel.ExtensionManager.Service <ILibraryViewCustomization>(); if (customization == null) { return; } //Register the icon resource /*customization.RegisterResourceStream("/icons/Category.AdvanceSteel.svg", * GetResourceStream("Dynamo.Applications.Resources.Category.AdvanceSteel.svg"));*/ //Read the steelSpec from the resource stream LayoutSpecification steelSpecs; using (Stream stream = GetResourceStream("Dynamo.Applications.Resources.LayoutSpecs.json")) { steelSpecs = LayoutSpecification.FromJSONStream(stream); } //The steelSpec should have only one section, add all its child elements to the customization var elements = steelSpecs.sections.First().childElements; customization.AddElements(elements); //add all the elements to default section }
/// <summary> /// Updates the Libarary Layout spec to include layout for Revit nodes. /// The Revit layout spec is embeded as resource "LayoutSpecs.json". /// </summary> private static void UpdateLibraryLayoutSpec() { //Get the library view customization service to update spec var customization = revitDynamoModel.ExtensionManager.Service <ILibraryViewCustomization>(); if (customization == null) { return; } if (shutdownHandler == null && extCommandData != null) { //Make sure to notify customization for application closing, so that //the CEF can be shutdown for clean Revit exit shutdownHandler = () => customization.OnAppShutdown(); extCommandData.Application.ApplicationClosing += (o, _) => shutdownHandler(); } //Register the icon resource customization.RegisterResourceStream("/icons/Category.Revit.svg", GetResourceStream("Dynamo.Applications.Resources.Category.Revit.svg")); //Read the revitspec from the resource stream LayoutSpecification revitspec; using (Stream stream = GetResourceStream("Dynamo.Applications.Resources.LayoutSpecs.json")) { revitspec = LayoutSpecification.FromJSONStream(stream); } //The revitspec should have only one section, add all its child elements to the customization var elements = revitspec.sections.First().childElements; // Extend it with the layoutSpecs from internal nodes var internalNodesLayouts = DynamoRevitInternalNodes.GetLayoutSpecsFiles(); foreach (var layoutSpecsFile in internalNodesLayouts) { try { LayoutSpecification spec = LayoutSpecification.FromJSONString(File.ReadAllText(layoutSpecsFile)); var revitSection = spec.sections.First(); var revitCategory = revitSection.childElements.First(); var revitCategoryToExtend = elements.First(elem => elem.text == "Revit"); revitCategoryToExtend.childElements.AddRange(revitCategory.childElements); } catch (Exception ex) { Console.WriteLine(string.Format("Exception while trying to load {0}", layoutSpecsFile)); } } customization.AddElements(elements); //add all the elements to default section }
/// <summary> /// 构造函数 /// </summary> /// <param name="resource">The resource name of json resource in the given assembly.</param> /// <param name="assembly">Assembly which contains the specified resource</param> public LayoutSpecProvider(ILibraryViewCustomization customization, string resource, Assembly assembly = null) : base(false) { assembly = assembly == null?Assembly.GetExecutingAssembly() : assembly; var stream = assembly.GetManifestResourceStream(resource); //Get the spec from the stream var spec = LayoutSpecification.FromJSONStream(stream); customization.AddSections(spec.sections); this.customization = customization; this.customization.SpecificationUpdated += OnSpecificationUpdate; }
public void ToJSONStream() { ILibraryViewCustomization customization = new LibraryViewCustomization(); var sections = new[] { "A", "B", "C" }.Select(s => new LayoutSection(s)); customization.AddSections(sections); using (var stream = customization.ToJSONStream()) { var spec = LayoutSpecification.FromJSONStream(stream); Assert.AreEqual(3, spec.sections.Count); Assert.AreEqual("A, B, C", string.Join(", ", spec.sections.Select(s => s.text))); } }
private static DynamoDictionaryEntry GetMatchingDictionaryEntry( IEnumerable <DynamoDictionaryEntry> dictEntrys, MdFileInfo info, LayoutSpecification spec) { // The DynamoDictionary only gives information about the name of the node // and the folder path, the MdFileInfo knows about the name of the node and // its namespace. The DynamoDictionary Folder path is the same as the namespace // except its separated by "/" instead of ".". // In order to find the correct dict entry we need to convert the namespace // into a folder path, and then get the entry where the folder path and name is matching. var infoNameSpaceFolderPath = ConvertNamespaceToDictionaryFolderPath(info.NodeNamespace); var infoCategoryFolderPath = ConvertNamespaceToDictionaryFolderPath(info.FullCategory); // First we try and find a match using the fileInfo directly. // There are cases where a LayoutSpecification is not provided // and therefor we need to find a match from the fileInfo directly. // There are also instances where the particular node/namespace // has not been added to the LayoutSpecification (I think!!) which is // another reason to always try and make the match using the fileInfo directly first. var matchingEntry = dictEntrys .Where(x => x.FolderPath.StartsWith(infoNameSpaceFolderPath) || x.FolderPath.StartsWith(infoCategoryFolderPath) && x.Name == info.NodeName) .FirstOrDefault(); // If we couldn't find a match using the fileInfo directly and a LayoutSpecification is provided // we try and find a match using that. if (matchingEntry is null && spec != null) { if (TryGetMatchingEntryFromLayoutSpec(spec.sections.Cast <LayoutElement>().ToList(), dictEntrys, info, string.Empty, out matchingEntry)) { return(matchingEntry); } } return(matchingEntry); }
/// <summary> /// Sets the given specification as the current library layout /// specification by overwriting the current one. /// </summary> public void SetSpecification(LayoutSpecification specification) { root = specification; RaiseSepcificationUpdated(); }
/// <summary> /// Creates markdown files from the given collection of fileInfos /// </summary> /// <param name="fileInfos">Collection of files to create</param> /// <param name="outputDir">Folder path where files should be created</param> /// <param name="overWrite">if true, files in outputDir will be overwritten</param> /// <param name="compressImages">if true images matched from dictionary will be compressed (if possible)</param> /// <param name="compressGifs">if true animated gifs matched from dictionary will be compressed (if possible)</param> /// <param name="dictionaryPath">path to dictionary json file</param> /// <param name="layoutSpec">path to layout spec json</param> internal static void CreateMdFilesFromFileNames( IEnumerable <MdFileInfo> fileInfos, string outputDir, bool overWrite, bool compressImages = false, bool compressGifs = false, string dictionaryPath = null, string layoutSpec = null) { ImageOptimizer optimizer = null; LayoutSpecification spec = null; List <DynamoDictionaryEntry> dictEntrys = null; string examplesDirectory = ""; Console.WriteLine($"Starting generation of {fileInfos.Count()} markdown files..."); // If there is a Dictionary path provided we do a couple of things. if (!string.IsNullOrEmpty(dictionaryPath) && File.Exists(dictionaryPath)) { // First we create DynamoDictionaryEntry's from the dictionary Json file. // This reflects the state of https://github.com/DynamoDS/DynamoDictionary at commit 1c259e6549de899793c1f99724c0535e9db46ad0 var dictionaryJson = File.ReadAllText(dictionaryPath); dictEntrys = JsonConvert.DeserializeObject <List <DynamoDictionaryEntry> >(dictionaryJson); // Then we save a reference to the `EXAMPLES` folder from the Dynamo Dictionary repo. // This folder contains all images and sample files used in the dictionary. var mainDirectory = new FileInfo(dictionaryPath).Directory; examplesDirectory = Path.Combine(mainDirectory.FullName, "EXAMPLES"); if (compressImages) { optimizer = new ImageOptimizer(); optimizer.OptimalCompression = true; } if (!string.IsNullOrEmpty(layoutSpec)) { var layoutSpecString = File.ReadAllText(layoutSpec); spec = JsonConvert.DeserializeObject <LayoutSpecification>(layoutSpecString); } } var filesCreatedCount = 0; foreach (var info in fileInfos) { var fileName = $"{info.FileName}.md"; var filePath = Path.Combine(outputDir, fileName); var fileInfo = new FileInfo(filePath); if (File.Exists(filePath) && !overWrite) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"Creation of {fileName} was skipped as the file already exist and the --overwrite flag was set to false"); Console.ResetColor(); continue; } string fileContent = null; // If there are any dictEntrys, we try and match the current fileInfo with an entry in the dictionary. // If a match is found the fileContent is set with the information in that entry. if (dictEntrys != null) { DynamoDictionaryEntry matchingEntry = GetMatchingDictionaryEntry(dictEntrys, info, spec); if (matchingEntry != null) { fileContent = GetContentFromDictionaryEntry(matchingEntry, examplesDirectory, optimizer, compressGifs, fileInfo); } } // If there are no dictEntrys or no match could be found, we set the fileContent to the default content. if (fileContent is null) { fileContent = GetDefaultContent(info.NodeName); // If we get to here and there aren't any dictEntrys, that means the dictionary is missing an entry for this node // we log this to the console. if (dictEntrys != null) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"No matching Dictionary entry found for {fileName} - file will only contain default content."); Console.ResetColor(); } } try { using (StreamWriter sw = File.CreateText(filePath)) { sw.WriteLine(fileContent); } } catch (Exception e) { CommandHandler.LogExceptionToConsole(e); continue; } filesCreatedCount++; } Console.WriteLine($"{filesCreatedCount} documentation files created"); }
protected LayoutMap() { Specification = new LayoutSpecification <TLayout, TSchema>(); }