Recently added the feature of the note writing style to the Cloudnotes desktop client. When a user creates a new note, you can choose a note-writing style when you enter a note title, with the default style (default), parchment style (leather Paper), and Word 2013 styles provided by the installation package (Microsoft Word 2013). When you choose a note style, you also have a preview feature that lets you preview the style effect directly:
Of course, in order to facilitate the operation, the user can select the default style in the settings interface, so that each time you create a new note, the default style will be automatically selected, reducing the number of user operations. The settings for the default style in the interface are set as follows:
Now, let me briefly explain how the entire style system is designed and implemented.
Style system
Like the plug-in system, the styling system also needs to read the external style files and then list all the reading styles in the settings interface. Therefore, in the Cloudnotes desktop client, the styles are customizable and extensible. The next section provides details on how to customize the style. In the case of the style system itself, it has a similar behavioral feature of the plug-in system: a central component is needed to manage all the styles and, when needed, to find the desired style definition through this central component. So, in the first step of implementing the styling system, I reconstructed the existing plug-in system.
External resource Manager (Externalresourcemanager)
As mentioned above, both the plug-in system and the style system need to read the external file, so I abstracted it into an external resource manager component that is primarily responsible for managing the data by reading external files, converting the file data into resources (plug-in or style) data. Therefore, the plug-In Manager (Extensionmanager) and the style Manager (Stylemanager) are an implementation of the external resource Manager (Externalresourcemanager), except that they are read and used differently for external files , and the data being processed is not the same.
First, in the load method of the Externalresourcemanager abstract class, search for all files that match the search criteria, based on the path passed by the constructor, and load the resource from each file that meets the search criteria by Loadresources abstract method:
<summary>///Loads the resources into the current manager.///</summary>public void Load () { if (Direct Ory. Exists (This.path)) { var resourcefiles = directory.enumeratefiles (This.path, This.searchpattern, searchoption.alldirectories); foreach (Var resourcefile in resourcefiles) { try { var res = loadresources (resourcefile); if (res! = NULL && res. Any ()) { foreach (var resource in res) { this.resources.Add (resource.id, Resource); } } } Catch { } } }}
Then, Extensionmanager in the implementation of the Loadresources method, With the Assembly.LoadFrom call, the assembly is read into memory, and the extension object is created using Activator.CreateInstance and then returned to the base class for management:
protected override ienumerable<extension> Loadresources (string fileName) { var assembly = Assembly.LoadFrom ( FileName); var result = new list<extension> (); foreach (var type in assembly. Getexportedtypes ()) { if (type. IsDefined (typeof (ExtensionAttribute)) && type. IsSubclassOf (typeof (Extension))) { try { var extensionloaded = (Extension) Activator.CreateInstance (type); This. Onresourceloaded (extensionloaded); Result. ADD (extensionloaded); } Catch { }}} return result;
And in the implementation of the Loadresources method of Stylemanager, the incoming file is extracted in zip, The Metadata.json file is read from to get the basic definition information of the style, and the Style.css file is read from it to get the details of the style, and then the JSON library is used to deserialize the Metadata.json and get the style object. Finally, the style object is returned to the base class for management:
protected override ienumerable<style> Loadresources (string fileName) {try {var extractedcontent = new Dictionary<string, string> (); var zipfile = new ZipFile (fileName); foreach (ZipEntry entry in ZipFile) {if (!entry. Isfile | | (String.Compare (entry. Name, Metadatafilename, stringcomparison.invariantcultureignorecase)! = 0 && string.compare (entry. Name, Stylefilename, stringcomparison.invariantcultureignorecase)! = 0)) continue; var buffer = new byte[4000]; var entrystream = Zipfile.getinputstream (entry); using (MemoryStream MemoryStream = new MemoryStream ()) {streamutils.copy (Entrystream, Memorystr EAM, buffer); Extractedcontent[entry. Name] = Encoding.ASCII.GetString (Memorystream.toarray ()); }} if (Extractedcontent.containskey (metadatafilename) && ExtractedcontEnt. ContainsKey (Stylefilename)) {var style = jsonconvert.deserializeobject<style> (extractedcontent[me Tadatafilename]); if (style.id = = Guid.Empty) return null; Style. Content = Extractedcontent[stylefilename]; Return new[] {style}; }} catch {} return null;}
In the case of style data, it contains the ID, style name, style description, creation date, author, and style code (defined in the Style.css file), and the style object holds the data and is used in scenes such as settings pages and new note creation.
The application principle of the style
In fact, the principle of the application of the style is very simple, that is, when creating a new note, use the contents of the Style.css in the style file to replace the placeholder in the Style label section under the head of the empty HTML document. In Cloudnotes, an empty HTML document is defined as follows:
Say it is an empty HTML document, not that it is an empty string, but because the body part is nothing. Suppose the styles in Style.css are as follows:
body { color:red;}
So, the resulting notes are:
It is worth mentioning that, in the Cloudnotes desktop client, the implementation of the style system is relatively simple, so in addition to the Metadata.json and style.css two files, the other files will be ignored. If you need to use an external file as a resource for a style, such as you want to be able to specify a background picture, you should convert the picture data to Base64 and then use Data:image to specify the URL of the picture.
Custom stylesThe customization of the Cloudnotes desktop client note-writing style is also very simple, and the style file itself is a zip compressed file with the style extension. To customize the style, first create a new Metadata.json file with the following contents:
{ "ID": "f04f9079-ec4e-4739-93c5-473607bea79e", //The GUID of the style "name": "Default", //style name " Description ":" Cloudnotes Default style ", //Style description " Author ":" Sunny Chen ", //Style author " CreationDate ":" 8/ 8/2015 " //Style creation date}
Then in Metadata.json the same path, create a new Style.css file, the content of the file is believed that everyone knows what is the CSS style. After two files are ready, compress them into a zip file, then change the extension to style and copy it to the Styles subdirectory of the Cloudnotes desktop client installation path. After restarting the Cloudnotes desktop client, you can see and select this custom style in the new Notes and Settings screen. Note that the zip file can contain only Metadata.json and style.css two files, cannot be placed in subdirectories, or the desktop client will not be able to read style information.
The following is a parchment-style note effect that is not visible in previous versions of the desktop client.
Cloudnotes Desktop Client article: support for note writing styles