diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Editors/FileSystem/Commands.uexml b/Content/UniversalEditor.Content.PlatformIndependent/Editors/FileSystem/Commands.uexml index 72ed3914..799f1240 100644 --- a/Content/UniversalEditor.Content.PlatformIndependent/Editors/FileSystem/Commands.uexml +++ b/Content/UniversalEditor.Content.PlatformIndependent/Editors/FileSystem/Commands.uexml @@ -49,7 +49,7 @@ - + @@ -149,6 +149,22 @@ + + + + + + + + + + + + + + + + diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Synthesized/MenuBar.uexml b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Synthesized/MenuBar.uexml index a3a84a4a..669bafe1 100644 --- a/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Synthesized/MenuBar.uexml +++ b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Synthesized/MenuBar.uexml @@ -74,8 +74,6 @@ - - diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Waveform/Commands.uexml b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Waveform/Commands.uexml index 3d071c64..db27dc7b 100644 --- a/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Waveform/Commands.uexml +++ b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Audio/Waveform/Commands.uexml @@ -3,25 +3,7 @@ - - - - - - - - - - - - - - - - - - diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia3D/Model/Icons/cube.png b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia3D/Model/Icons/cube.png new file mode 100644 index 00000000..6f430f81 Binary files /dev/null and b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia3D/Model/Icons/cube.png differ diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia3D/Model/Icons/cube.svg b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia3D/Model/Icons/cube.svg new file mode 100644 index 00000000..b03a6dd1 --- /dev/null +++ b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia3D/Model/Icons/cube.svg @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia3D/Model/Icons/sphere.png b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia3D/Model/Icons/sphere.png new file mode 100644 index 00000000..c35485d6 Binary files /dev/null and b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia3D/Model/Icons/sphere.png differ diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia3D/Model/Icons/sphere.svg b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia3D/Model/Icons/sphere.svg new file mode 100644 index 00000000..3419275a --- /dev/null +++ b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia3D/Model/Icons/sphere.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Extensions/Multimedia3D/Languages/English.uexml b/Content/UniversalEditor.Content.PlatformIndependent/Extensions/Multimedia3D/Languages/English.uexml new file mode 100644 index 00000000..53ab99db --- /dev/null +++ b/Content/UniversalEditor.Content.PlatformIndependent/Extensions/Multimedia3D/Languages/English.uexml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj b/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj index 8957004f..69474d60 100644 --- a/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj +++ b/Content/UniversalEditor.Content.PlatformIndependent/UniversalEditor.Content.PlatformIndependent.csproj @@ -326,6 +326,9 @@ + + + @@ -363,6 +366,8 @@ + + @@ -373,6 +378,8 @@ + + diff --git a/Libraries/UniversalEditor.Essential/DataFormats/Markup/XML/CommonXMLSchemas.cs b/Libraries/UniversalEditor.Essential/DataFormats/Markup/XML/CommonXMLSchemas.cs new file mode 100644 index 00000000..773bbb42 --- /dev/null +++ b/Libraries/UniversalEditor.Essential/DataFormats/Markup/XML/CommonXMLSchemas.cs @@ -0,0 +1,62 @@ +// +// XMLSchemas.cs - provides common XML schema definitions used in a wide variety of applications +// +// Author: +// Michael Becker +// +// Copyright (c) 2021 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +namespace UniversalEditor.DataFormats.Markup.XML +{ + /// + /// Provides common XML schema definitions used in a wide variety of applications. + /// + public static class CommonXMLSchemas + { + /// + /// The /elements/1.1/ namespace was created in 2000 for the RDF representation of the fifteen-element + /// Dublin Core and has been widely used in data for more than twenty years. This namespace corresponds + /// to the original scope of ISO 15836, which was published first in 2003 and last revised in 2017 as + /// ISO 15836-1:2017. + /// + /// The XML schema for the original Dublin Core namespace. + public static string DublinCore { get; } = "http://purl.org/dc/elements/1.1/"; + /// + /// The /terms/ namespace was originally created in 2001 for identifying new terms coined outside of the + /// original fifteen-element Dublin Core. In 2008, in the context of defining formal semantic constraints + /// for DCMI metadata terms in support of RDF applications, the original fifteen elements themselves were + /// mirrored in the /terms/ namespace. As a result, there exists both a dc:date (http://purl.org/dc/elements/1.1/date) + /// with no formal range and a corresponding dcterms:date (http://purl.org/dc/terms/date) with a formal + /// range of "literal". While these distinctions are significant for creators of RDF applications, most users + /// can safely treat the fifteen parallel properties as equivalent. The most useful properties and classes of + /// DCMI Metadata Terms have now been published as ISO 15836-2:2019 [ISO 15836-2:2019]. While the /elements/1.1/ + /// namespace will be supported indefinitely, DCMI gently encourages use of the /terms/ namespace. + /// + /// The XML schema for the Dublin Core Terms namespace. + public static string DublinCoreTerms { get; } = "http://purl.org/dc/terms/"; + /// + /// The /dcmitype/ namespace was created in 2001 for the DCMI Type Vocabulary, which defines classes for + /// basic types of thing that can be described using DCMI metadata terms. + /// + /// The XML schema for the Dublin Core DCMI Type namespace. + public static string DublinCoreDCMIType { get; } = "http://purl.org/dc/dcmitype/"; + /// + /// The /dcam/ namespace was created in 2008 for terms used in the description of DCMI metadata terms. + /// + /// The XML schema for the Dublin Core DCAM namespace. + public static string DublinCoreDCAM { get; } = "http://purl.org/dc/dcam/"; + } +} diff --git a/Libraries/UniversalEditor.Essential/DataFormats/Markup/XML/XMLDataFormat.cs b/Libraries/UniversalEditor.Essential/DataFormats/Markup/XML/XMLDataFormat.cs index d4c1964b..e1720aa6 100644 --- a/Libraries/UniversalEditor.Essential/DataFormats/Markup/XML/XMLDataFormat.cs +++ b/Libraries/UniversalEditor.Essential/DataFormats/Markup/XML/XMLDataFormat.cs @@ -21,7 +21,7 @@ using System; using System.Collections.Generic; - +using System.Text; using UniversalEditor.ObjectModels.Markup; using UniversalEditor.ObjectModels.PropertyList; @@ -116,7 +116,7 @@ namespace UniversalEditor.DataFormats.Markup.XML if (element is MarkupTagElement) { MarkupTagElement tag = element as MarkupTagElement; - tw.Write(indent + Settings.TagBeginChar.ToString() + element.FullName); + tw.Write(indent + Settings.TagBeginChar.ToString() + GetFullName(element)); if (tag.Attributes.Count > 0) { tw.Write(" "); @@ -199,6 +199,40 @@ namespace UniversalEditor.DataFormats.Markup.XML } } } + + private string GetFullName(MarkupElement element) + { + if (element is MarkupTagElement) + { + if ((element as MarkupTagElement).XMLSchema != null) + { + StringBuilder sb = new StringBuilder(); + sb.Append(GetPrefixForXMLSchema(element.ParentObjectModel, (element as MarkupTagElement).XMLSchema)); + sb.Append(':'); + sb.Append(element.Name); + return sb.ToString(); + } + } + return element.FullName; + } + + private string GetPrefixForXMLSchema(MarkupObjectModel mom, string xmlSchema) + { + foreach (MarkupElement el in mom.Elements) + { + if (el is MarkupTagElement) + { + foreach (MarkupAttribute att in (el as MarkupTagElement).Attributes) + { + if (att.Namespace == "xmlns" && att.Value == xmlSchema) + return att.Name; + } + break; + } + } + throw new InvalidOperationException(String.Format("xml prefix not found for schema '{0}'", xmlSchema)); + } + public void WriteStartDocument() { this.WriteStartPreprocessor("xml"); diff --git a/Libraries/UniversalEditor.Essential/ObjectModels/Markup/MarkupContainerElement.cs b/Libraries/UniversalEditor.Essential/ObjectModels/Markup/MarkupContainerElement.cs index 0d142c5f..19b12a4b 100644 --- a/Libraries/UniversalEditor.Essential/ObjectModels/Markup/MarkupContainerElement.cs +++ b/Libraries/UniversalEditor.Essential/ObjectModels/Markup/MarkupContainerElement.cs @@ -83,10 +83,14 @@ namespace UniversalEditor.ObjectModels.Markup return basetag; } + private string _XMLSchema = null; public string XMLSchema { get { + if (_XMLSchema != null) + return _XMLSchema; + if (this.Namespace == null) return null; @@ -103,6 +107,33 @@ namespace UniversalEditor.ObjectModels.Markup return null; } + set + { + if (this.ParentObjectModel == null) + { + _XMLSchema = value; + return; + } + + for (int i = 0; i < this.ParentObjectModel.Elements.Count; i++) + { + MarkupTagElement tagTopLevel = (this.ParentObjectModel.Elements[i] as MarkupTagElement); + if (tagTopLevel == null) + continue; + + foreach (MarkupAttribute att in tagTopLevel.Attributes) + { + if (att.Namespace == "xmlns") + { + if (att.Value == value) + { + Namespace = att.Name; + break; + } + } + } + } + } } protected override void UpdateParentObjectModel() diff --git a/Libraries/UniversalEditor.Essential/ObjectModels/Markup/MarkupTagElement.cs b/Libraries/UniversalEditor.Essential/ObjectModels/Markup/MarkupTagElement.cs index dd84d596..f939b80e 100644 --- a/Libraries/UniversalEditor.Essential/ObjectModels/Markup/MarkupTagElement.cs +++ b/Libraries/UniversalEditor.Essential/ObjectModels/Markup/MarkupTagElement.cs @@ -29,6 +29,21 @@ namespace UniversalEditor.ObjectModels.Markup /// public class MarkupTagElement : MarkupContainerElement { + public MarkupTagElement() + { + } + public MarkupTagElement(string fullName, string innerMarkup) + { + FullName = fullName; + Value = innerMarkup; + } + public MarkupTagElement(string schema, string name, string innerMarkup) + { + XMLSchema = schema; + Name = name; + Value = innerMarkup; + } + /// /// Combines the attributes and child elements of this with the given . /// diff --git a/Libraries/UniversalEditor.Essential/ObjectModels/PropertyList/PropertyListObjectModel.cs b/Libraries/UniversalEditor.Essential/ObjectModels/PropertyList/PropertyListObjectModel.cs index 5b2935f8..bdd6ff9f 100644 --- a/Libraries/UniversalEditor.Essential/ObjectModels/PropertyList/PropertyListObjectModel.cs +++ b/Libraries/UniversalEditor.Essential/ObjectModels/PropertyList/PropertyListObjectModel.cs @@ -46,11 +46,41 @@ namespace UniversalEditor.ObjectModels.PropertyList } public override void CopyTo(ObjectModel objectModel) { - PropertyListObjectModel omb = objectModel as PropertyListObjectModel; - if (omb == null) throw new ObjectModelNotSupportedException(); + PropertyListObjectModel clone = objectModel as PropertyListObjectModel; + if (clone == null) throw new ObjectModelNotSupportedException(); - // omb.Combine(this); + Combine(clone); } + + public void Combine(PropertyListObjectModel clone) + { + foreach (PropertyListItem item in Items) + { + if (item is Property) + { + if (clone.Items.Contains(item.Name) && clone.Items[item.Name] is Property) + { + (clone.Items[item.Name] as Property).Value = (item as Property).Value; + } + else + { + clone.Items.Add(((Property)item).Clone() as Property); + } + } + else if (item is Group) + { + if (clone.Items.Contains(item.Name) && clone.Items[item.Name] is Group) + { + (clone.Items[item.Name] as Group).Combine(item as Group); + } + else + { + clone.Items.Add(((Group)item).Clone() as Group); + } + } + } + } + public T GetValue(string propertyName) { return this.GetValue(new string[] diff --git a/Libraries/UniversalEditor.Essential/UniversalEditor.Essential.csproj b/Libraries/UniversalEditor.Essential/UniversalEditor.Essential.csproj index 575fa508..da6d2b1e 100644 --- a/Libraries/UniversalEditor.Essential/UniversalEditor.Essential.csproj +++ b/Libraries/UniversalEditor.Essential/UniversalEditor.Essential.csproj @@ -217,6 +217,7 @@ + diff --git a/Libraries/UniversalEditor.UserInterface/Common/Reflection.cs b/Libraries/UniversalEditor.UserInterface/Common/Reflection.cs index ec94f3f7..59eb0354 100644 --- a/Libraries/UniversalEditor.UserInterface/Common/Reflection.cs +++ b/Libraries/UniversalEditor.UserInterface/Common/Reflection.cs @@ -296,6 +296,20 @@ namespace UniversalEditor.UserInterface.Common er.Variables.Add(varr); } } + + + MarkupTagElement tagCommandBars = (tagEditor.Elements["CommandBars"] as MarkupTagElement); + if (tagCommandBars != null) + { + foreach (MarkupElement elCommandBar in tagCommandBars.Elements) + { + CommandBar cb = CommandBarLoader.LoadCommandBarXML(elCommandBar as MarkupTagElement); + if (cb != null) + { + er.CommandBars.Add(cb); + } + } + } } } } diff --git a/Libraries/UniversalEditor.UserInterface/EditorApplication.cs b/Libraries/UniversalEditor.UserInterface/EditorApplication.cs index 406bf2d3..d56b02dc 100644 --- a/Libraries/UniversalEditor.UserInterface/EditorApplication.cs +++ b/Libraries/UniversalEditor.UserInterface/EditorApplication.cs @@ -829,30 +829,13 @@ namespace UniversalEditor.UserInterface Editor ed = LastWindow.GetCurrentEditor(); if (ed == null) return; - Accessor acc = ed.ObjectModel?.Accessor ?? (ed.Parent as Pages.EditorPage)?.Document?.Accessor; - - // we cannot yet bookmark a file that does not yet exist. (this would be akin to creating a shortcut to a template I guess...?) - if (acc == null) return; - - // FIXME: BookmarksAdd copypasta - string filename = acc.GetFileName(); - BookmarksManager.FileNames.Add(filename); - - Command cmdBookmarks = Application.Instance.Commands["Bookmarks"]; - if (cmdBookmarks.Items.Count == 4) - { - cmdBookmarks.Items.Add(new SeparatorCommandItem()); - } - - ((UIApplication)Application.Instance).Commands.Add(new Command(String.Format("{0}", (((EditorApplication)Application.Instance).BookmarksManager.FileNames.Count - 1).ToString()), System.IO.Path.GetFileName(((EditorApplication)Application.Instance).BookmarksManager.FileNames[(BookmarksManager.FileNames.Count - 1)]))); - ((UIApplication)Application.Instance).Commands["Bookmarks"].Items.Add(new CommandReferenceCommandItem(String.Format("Bookmarks_Bookmark{0}", (BookmarksManager.FileNames.Count - 1).ToString()))); - - Application.Instance.AttachCommandEventHandler(String.Format("Bookmarks_Bookmark{0}", (((EditorApplication)Application.Instance).BookmarksManager.FileNames.Count - 1).ToString()), Bookmarks_Bookmark_Click); + AddBookmark(ed.ObjectModel?.Accessor ?? (ed.Parent as Pages.EditorPage)?.Document?.Accessor); ShowBookmarksManagerDialog(); }); Application.Instance.AttachCommandEventHandler("BookmarksAddAll", delegate (object sender, EventArgs e) { Page[] pages = LastWindow.GetPages(); + for (int i = 0; i < pages.Length; i++) { if (pages[i] is Pages.EditorPage) @@ -860,20 +843,7 @@ namespace UniversalEditor.UserInterface Pages.EditorPage ep = (pages[i] as Pages.EditorPage); Editor ed = (ep.Controls[0] as Editor); - // FIXME: BookmarksAdd copypasta - string filename = ed.ObjectModel.Accessor.GetFileName(); - BookmarksManager.FileNames.Add(filename); - - Command cmdBookmarks = ((UIApplication)Application.Instance).Commands["Bookmarks"]; - if (cmdBookmarks.Items.Count == 4) - { - cmdBookmarks.Items.Add(new SeparatorCommandItem()); - } - - Application.Instance.Commands.Add(new Command(String.Format("Bookmarks_Bookmark{0}", (((EditorApplication)Application.Instance).BookmarksManager.FileNames.Count - 1)), System.IO.Path.GetFileName(((EditorApplication)Application.Instance).BookmarksManager.FileNames[(BookmarksManager.FileNames.Count - 1)]))); - Application.Instance.Commands["Bookmarks"].Items.Add(new CommandReferenceCommandItem(String.Format("Bookmarks_Bookmark{0}", ((EditorApplication)Application.Instance).BookmarksManager.FileNames.Count - 1))); - - Application.Instance.AttachCommandEventHandler(String.Format("Bookmarks_Bookmark{0}", (((EditorApplication)Application.Instance).BookmarksManager.FileNames.Count - 1).ToString()), Bookmarks_Bookmark_Click); + AddBookmark(ed.ObjectModel?.Accessor ?? (ed.Parent as Pages.EditorPage)?.Document?.Accessor); } } @@ -1029,6 +999,32 @@ namespace UniversalEditor.UserInterface #endregion } + /// + /// Adds a bookmark referencing the specified to the application's bookmarks menu. + /// + /// true, if bookmark was added, false otherwise. + /// The referencing the bookmark to add. + public bool AddBookmark(Accessor accessor) + { + // we cannot yet bookmark a file that does not yet exist. (this would be akin to creating a shortcut to a template I guess...?) + if (accessor == null) return false; + + string filename = accessor.GetFileName(); + BookmarksManager.FileNames.Add(filename); + + Command cmdBookmarks = Application.Instance.Commands["Bookmarks"]; + if (cmdBookmarks.Items.Count == 4) + { + cmdBookmarks.Items.Add(new SeparatorCommandItem()); + } + + ((UIApplication)Application.Instance).Commands.Add(new Command(String.Format("{0}", (((EditorApplication)Application.Instance).BookmarksManager.FileNames.Count - 1).ToString()), System.IO.Path.GetFileName(((EditorApplication)Application.Instance).BookmarksManager.FileNames[(BookmarksManager.FileNames.Count - 1)]))); + ((UIApplication)Application.Instance).Commands["Bookmarks"].Items.Add(new CommandReferenceCommandItem(String.Format("Bookmarks_Bookmark{0}", (BookmarksManager.FileNames.Count - 1).ToString()))); + + Application.Instance.AttachCommandEventHandler(String.Format("Bookmarks_Bookmark{0}", (((EditorApplication)Application.Instance).BookmarksManager.FileNames.Count - 1).ToString()), Bookmarks_Bookmark_Click); + return true; + } + void Td_HyperlinkClicked(object sender, TaskDialogHyperlinkClickedEventArgs e) { System.Diagnostics.Process.Start("https://www.gnu.org/licenses/gpl-3.0.en.html"); diff --git a/Libraries/UniversalEditor.UserInterface/EditorContext.cs b/Libraries/UniversalEditor.UserInterface/EditorContext.cs index 266231c8..086b7a2c 100644 --- a/Libraries/UniversalEditor.UserInterface/EditorContext.cs +++ b/Libraries/UniversalEditor.UserInterface/EditorContext.cs @@ -45,6 +45,10 @@ namespace UniversalEditor.UserInterface { Commands.Add(reference.Commands[i]); } + for (int i = 0; i < reference.CommandBars.Count; i++) + { + CommandBars.Add(reference.CommandBars[i]); + } for (int i = 0; i < reference.MenuBar.Items.Count; i++) { MenuItems.Add(reference.MenuBar.Items[i]); diff --git a/Libraries/UniversalEditor.UserInterface/EditorReference.cs b/Libraries/UniversalEditor.UserInterface/EditorReference.cs index 29a31aed..fe9b2f1b 100644 --- a/Libraries/UniversalEditor.UserInterface/EditorReference.cs +++ b/Libraries/UniversalEditor.UserInterface/EditorReference.cs @@ -30,6 +30,7 @@ namespace UniversalEditor.UserInterface public MarkupTagElement Configuration { get; set; } = null; public CommandBar MenuBar { get; } = new CommandBar(); + public CommandBar.CommandBarCollection CommandBars { get; } = new CommandBar.CommandBarCollection(); public Command.CommandCollection Commands { get; } = new Command.CommandCollection(); public PanelReference.PanelReferenceCollection Panels { get; } = new PanelReference.PanelReferenceCollection(); public EditorView.EditorViewCollection Views { get; } = new EditorView.EditorViewCollection(); diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.AddressBook.UserInterface/Editors/Contact/ContactEditor.cs b/Plugins.UserInterface/UniversalEditor.Plugins.AddressBook.UserInterface/Editors/Contact/ContactEditor.cs index 63f294c2..5bb4050f 100644 --- a/Plugins.UserInterface/UniversalEditor.Plugins.AddressBook.UserInterface/Editors/Contact/ContactEditor.cs +++ b/Plugins.UserInterface/UniversalEditor.Plugins.AddressBook.UserInterface/Editors/Contact/ContactEditor.cs @@ -59,6 +59,7 @@ namespace UniversalEditor.Editors.Contact this.Padding = new Padding(26); TabContainer sidebar = new TabContainer(); + sidebar.TabStyle = TabContainerTabStyle.Sidebar; #region Summary Panel { diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Synthesized/SynthesizedAudioEditor.Designer.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Synthesized/SynthesizedAudioEditor.Designer.cs index 3ca36355..1019bb88 100644 --- a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Synthesized/SynthesizedAudioEditor.Designer.cs +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Synthesized/SynthesizedAudioEditor.Designer.cs @@ -25,6 +25,8 @@ using MBS.Framework.UserInterface.Layouts; using UniversalEditor.UserInterface; using UniversalEditor.ObjectModels.Multimedia.Audio.Synthesized; +using System; +using MBS.Framework; namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized { @@ -35,6 +37,8 @@ namespace UniversalEditor.Editors.Multimedia.Audio.Synthesized InitializeComponent(); } + public MBS.Audio.ITransport Transport { get; set; } = null; + private static EditorReference _er = null; public override EditorReference MakeReference() { diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackWaveform.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackWaveform.cs index d9269f44..58ed8908 100644 --- a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackWaveform.cs +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/Controls/WaveformAudioEditorTrackWaveform.cs @@ -106,6 +106,8 @@ namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Au WaveformAudioEditorTrack track = (Parent as WaveformAudioEditorTrack); WaveformAudioObjectModel wave = track.ObjectModel; + if (wave.RawSamples == null) + return; ScrollBounds = new MBS.Framework.Drawing.Dimension2D(wave.RawSamples.Length, 0); diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/WaveformAudioEditor.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/WaveformAudioEditor.cs index ff763a12..5bda67bd 100644 --- a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/WaveformAudioEditor.cs +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Audio/Waveform/WaveformAudioEditor.cs @@ -43,6 +43,8 @@ namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Au return _er; } + public MBS.Audio.ITransport Transport { get; set; } = null; + public WaveformAudioEditor() { Layout = new BoxLayout(Orientation.Vertical); @@ -66,17 +68,21 @@ namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Au protected override void OnCreated(EventArgs e) { base.OnCreated(e); - Context.AttachCommandEventHandler("WaveformAudioEditor_ContextMenu_Playback_Play", delegate (object sender, EventArgs ee) - { - WaveformAudioObjectModel wave = (ObjectModel as WaveformAudioObjectModel); - if (wave == null) return; - // get the setting "Editors -> Audio -> Waveform -> Audio engine + Transport = new MBS.Audio.CustomTransport(Transport_Play, null, null); + } - // get the setting "Editors -> Audio -> Waveform -> Synchronize with JACK transport - AudioPlayer player = new AudioPlayer(); - player.Play(wave); - }); + private bool Transport_Play() + { + WaveformAudioObjectModel wave = (ObjectModel as WaveformAudioObjectModel); + if (wave == null) return false; + + // get the setting "Editors -> Audio -> Waveform -> Audio engine + + // get the setting "Editors -> Audio -> Waveform -> Synchronize with JACK transport + AudioPlayer player = new AudioPlayer(); + player.Play(wave); + return true; } public override void UpdateSelections() diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Plugins/Transport/TransportPlugin.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Plugins/Transport/TransportPlugin.cs new file mode 100644 index 00000000..00174853 --- /dev/null +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Plugins/Transport/TransportPlugin.cs @@ -0,0 +1,181 @@ +// +// TransportPlugin.cs +// +// Author: +// Michael Becker +// +// Copyright (c) 2021 Mike Becker's Software +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +using System; +using MBS.Framework; +using MBS.Framework.UserInterface; +using MBS.Framework.UserInterface.Dialogs; +using UniversalEditor.UserInterface; + +namespace UniversalEditor.Plugins.Multimedia.UserInterface.Plugins.Transport +{ + public class TransportPlugin : UserInterfacePlugin + { + public TransportPlugin() + { + ID = new Guid("{02e071ec-b2cd-4a72-999f-3b626e06d609}"); + Title = "Transport Plugin"; + Context = new UIContext(ID, "Transport Plugin"); + + cbTransport = new CommandBar("cbTransport", "Transport", new CommandItem[] + { + new CommandReferenceCommandItem("Transport_Rewind"), + new CommandReferenceCommandItem("Transport_Back"), + new CommandReferenceCommandItem("Transport_Play"), + new CommandReferenceCommandItem("Transport_Forward"), + new CommandReferenceCommandItem("Transport_End") + }); + } + + private CommandBar cbTransport = null; + private CommandReferenceCommandItem miTransport = null; + + void Handle_EditorChanging(object sender, EditorChangingEventArgs e) + { + if (e.CurrentEditor == null) + return; + + Type t = e.CurrentEditor.GetType(); + System.Reflection.PropertyInfo piTransport = t.GetProperty("Transport", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); + if (piTransport != null && piTransport.PropertyType == typeof(MBS.Audio.ITransport)) + { + if (!e.CurrentEditor.Context.CommandBars.Contains(cbTransport)) + { + e.CurrentEditor.Context.CommandBars.Add(cbTransport); + } + + if (!e.CurrentEditor.Context.MenuItems.Contains(miTransport)) + { + e.CurrentEditor.Context.MenuItems.Add(miTransport); + } + } + } + + + protected override void InitializeInternal() + { + base.InitializeInternal(); + + Context.Commands.Add(new Command("Transport_Rewind", "_Rewind") { StockType = StockType.MediaPrevious }); + Context.Commands.Add(new Command("Transport_Back", "_Back") { StockType = StockType.MediaRewind }); + Context.Commands.Add(new Command("Transport_Play", "_Play") { StockType = StockType.MediaPlay }); + Context.Commands.Add(new Command("Transport_Forward", "_Forward") { StockType = StockType.MediaForward }); + Context.Commands.Add(new Command("Transport_End", "_End") { StockType = StockType.MediaNext }); + Context.Commands.Add(new Command("Transport_Transport", "P_layback", new CommandItem[] + { + new CommandReferenceCommandItem("Transport_Rewind"), + new CommandReferenceCommandItem("Transport_Back"), + new CommandReferenceCommandItem("Transport_Play"), + new CommandReferenceCommandItem("Transport_Forward"), + new CommandReferenceCommandItem("Transport_End"), + })); + + Context.AttachCommandEventHandler("Transport_Rewind", Transport_Rewind); + Context.AttachCommandEventHandler("Transport_Back", Transport_Back); + Context.AttachCommandEventHandler("Transport_Play", Transport_Play); + Context.AttachCommandEventHandler("Transport_Forward", Transport_Forward); + Context.AttachCommandEventHandler("Transport_End", Transport_End); + + ((EditorApplication)Application.Instance).EditorChanging += Handle_EditorChanging; + + + miTransport = new CommandReferenceCommandItem("Transport_Transport"); + miTransport.InsertAfterID = "Project"; + } + + private void Transport_End(object sender, EventArgs e) + { + Editor ed = (((UIApplication)Application.Instance).CurrentWindow as UniversalEditor.UserInterface.MainWindow)?.GetCurrentEditor(); + Type t = ed?.GetType(); + System.Reflection.PropertyInfo piTransport = t?.GetProperty("Transport", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); + MBS.Audio.ITransport transport = (piTransport?.GetValue(ed, null) as MBS.Audio.ITransport); + + if (transport == null) + { + MessageDialog.ShowDialog("Transport unavailable", "Error", MessageDialogButtons.OK, MessageDialogIcon.Error); + return; + } + + } + + private void Transport_Forward(object sender, EventArgs e) + { + Editor ed = (((UIApplication)Application.Instance).CurrentWindow as UniversalEditor.UserInterface.MainWindow)?.GetCurrentEditor(); + Type t = ed?.GetType(); + System.Reflection.PropertyInfo piTransport = t?.GetProperty("Transport", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); + MBS.Audio.ITransport transport = (piTransport?.GetValue(ed, null) as MBS.Audio.ITransport); + + if (transport == null) + { + MessageDialog.ShowDialog("Transport unavailable", "Error", MessageDialogButtons.OK, MessageDialogIcon.Error); + return; + } + + } + + private void Transport_Play(object sender, EventArgs e) + { + Editor ed = (((UIApplication)Application.Instance).CurrentWindow as UniversalEditor.UserInterface.MainWindow)?.GetCurrentEditor(); + Type t = ed?.GetType(); + System.Reflection.PropertyInfo piTransport = t?.GetProperty("Transport", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); + MBS.Audio.ITransport transport = (piTransport?.GetValue(ed, null) as MBS.Audio.ITransport); + + if (transport == null) + { + MessageDialog.ShowDialog("Transport unavailable", "Error", MessageDialogButtons.OK, MessageDialogIcon.Error); + return; + } + + transport.Play(); + } + + private void Transport_Back(object sender, EventArgs e) + { + Editor ed = (((UIApplication)Application.Instance).CurrentWindow as UniversalEditor.UserInterface.MainWindow)?.GetCurrentEditor(); + Type t = ed?.GetType(); + System.Reflection.PropertyInfo piTransport = t?.GetProperty("Transport", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); + MBS.Audio.ITransport transport = (piTransport?.GetValue(ed, null) as MBS.Audio.ITransport); + + if (transport == null) + { + MessageDialog.ShowDialog("Transport unavailable", "Error", MessageDialogButtons.OK, MessageDialogIcon.Error); + return; + } + + + } + + private void Transport_Rewind(object sender, EventArgs e) + { + Editor ed = (((UIApplication)Application.Instance).CurrentWindow as UniversalEditor.UserInterface.MainWindow)?.GetCurrentEditor(); + Type t = ed?.GetType(); + System.Reflection.PropertyInfo piTransport = t?.GetProperty("Transport", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public); + MBS.Audio.ITransport transport = (piTransport?.GetValue(ed, null) as MBS.Audio.ITransport); + + if (transport == null) + { + MessageDialog.ShowDialog("Transport unavailable", "Error", MessageDialogButtons.OK, MessageDialogIcon.Error); + return; + } + + transport.Stop(); + } + } +} diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface.csproj b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface.csproj index 6e28e675..365d8030 100644 --- a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface.csproj +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface.csproj @@ -60,6 +60,7 @@ + @@ -83,6 +84,8 @@ + + diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/Editors/Model/ModelEditor.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/Editors/Model/ModelEditor.cs index 9500ccaf..fa78e17e 100644 --- a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/Editors/Model/ModelEditor.cs +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia3D.UserInterface/Editors/Model/ModelEditor.cs @@ -27,6 +27,7 @@ using MBS.Framework.Rendering; using MBS.Framework.UserInterface; using MBS.Framework.UserInterface.Controls; using MBS.Framework.UserInterface.Dialogs; +using MBS.Framework.UserInterface.Input.Mouse; using MBS.Framework.UserInterface.Layouts; using UniversalEditor.ObjectModels.Multimedia3D.Model; @@ -46,18 +47,29 @@ namespace UniversalEditor.Plugins.Multimedia3D.UserInterface.Editors.Model { _er = base.MakeReference(); _er.SupportedObjectModels.Add(typeof(ModelObjectModel)); + + _er.Commands.Add(new Command("ModelEditor_Insert_Cube", "Cube") { ImageFileName = "Editors/Multimedia3D/Model/Icons/cube.png" }); + _er.Commands.Add(new Command("ModelEditor_Insert_Sphere", "Sphere") { ImageFileName = "Editors/Multimedia3D/Model/Icons/sphere.png" }); + _er.Commands.Add(new Command("ModelEditor_Insert_Plane", "Plane") { ImageFileName = "Editors/Multimedia3D/Model/Icons/plane.png" }); + + _er.CommandBars.Add(new CommandBar("ModelEditor_Insert", "Insert", new CommandItem[] + { + new CommandReferenceCommandItem("ModelEditor_Insert_Cube"), + new CommandReferenceCommandItem("ModelEditor_Insert_Sphere"), + new CommandReferenceCommandItem("ModelEditor_Insert_Plane"), + new SeparatorCommandItem() + })); } return _er; } public override void UpdateSelections() { - throw new NotImplementedException(); } protected override Selection CreateSelectionInternal(object content) { - throw new NotImplementedException(); + return null; } private OpenGLCanvas gla = null; @@ -67,6 +79,7 @@ namespace UniversalEditor.Plugins.Multimedia3D.UserInterface.Editors.Model this.Layout = new BoxLayout(Orientation.Vertical); gla = new OpenGLCanvas(); + gla.FocusOnClick = true; gla.Realize += gla_Realize; gla.Render += gla_Render; this.Controls.Add(gla, new BoxLayout.Constraints(true, true)); @@ -116,7 +129,7 @@ namespace UniversalEditor.Plugins.Multimedia3D.UserInterface.Editors.Model new VERTEX(-0.5f, -0.366f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f) }; - VertexArray[] vaos = null; + VertexArray vao = null; /// /// Computes the modelview projection @@ -176,6 +189,16 @@ namespace UniversalEditor.Plugins.Multimedia3D.UserInterface.Editors.Model void gla_Render(object sender, OpenGLCanvasRenderEventArgs e) { + if (fatalError) + return; + + if (e.Canvas == null) + { + MessageDialog.ShowDialog(String.Format("{0} . {1} {2} .\n\n", this._("Multimedia3D.Errors.CanvasInaccessible"), this._("Multimedia3D.Errors.RenderingUnavailable"), this._("Multimedia3D.Errors.CheckRequiredLibraries")), this._("Framework.Errors.GenericErrorTitle"), MessageDialogButtons.OK, MessageDialogIcon.Error); + fatalError = true; + return; + } + e.Canvas.Clear(Colors.Gray); if (p == null && !fatalError) @@ -185,7 +208,7 @@ namespace UniversalEditor.Plugins.Multimedia3D.UserInterface.Editors.Model string vtxFileName = ((UIApplication)Application.Instance).ExpandRelativePath("~/Editors/Multimedia3D/Model/Shaders/Default/default_vtx.glsl"); if (!System.IO.File.Exists(vtxFileName)) { - MessageDialog.ShowDialog(String.Format("Vertex shader not found . The rendering will be unavailable. Check to ensure the file exists and is readable .\n\n{0}", vtxFileName), "Error", MessageDialogButtons.OK, MessageDialogIcon.Error); + MessageDialog.ShowDialog(String.Format("{0} . {1} {2} .\n\n", this._("Multimedia3D.Errors.VertexShaderNotFound"), this._("Multimedia3D.Errors.RenderingUnavailable"), this._("Multimedia3D.Errors.CheckRequiredFile")), this._("Framework.Errors.GenericErrorTitle"), MessageDialogButtons.OK, MessageDialogIcon.Error); fatalError = true; p = null; return; @@ -197,7 +220,7 @@ namespace UniversalEditor.Plugins.Multimedia3D.UserInterface.Editors.Model string frgFileName = ((UIApplication)Application.Instance).ExpandRelativePath("~/Editors/Multimedia3D/Model/Shaders/Default/default_frg.glsl"); if (!System.IO.File.Exists(vtxFileName)) { - MessageDialog.ShowDialog(String.Format("Fragment shader not found . The rendering will be unavailable. Check to ensure the file exists and is readable .\n\n{0}", frgFileName), "Error", MessageDialogButtons.OK, MessageDialogIcon.Error); + MessageDialog.ShowDialog(String.Format("{0} . {1} {2} .\n\n", this._("Multimedia3D.Errors.FragmentShaderNotFound"), this._("Multimedia3D.Errors.RenderingUnavailable"), this._("Multimedia3D.Errors.CheckRequiredFile")), this._("Framework.Errors.GenericErrorTitle"), MessageDialogButtons.OK, MessageDialogIcon.Error); fatalError = true; p = null; return; @@ -220,11 +243,11 @@ namespace UniversalEditor.Plugins.Multimedia3D.UserInterface.Editors.Model } /* use the buffers in the VAO */ - if (vaos != null) + if (vao != null) { try { - vaos[0].Bind(); + vao.Bind(); /* draw the three vertices as a triangle */ e.Canvas.DrawArrays(RenderMode.Triangles, 0, vertex_data.Length); @@ -289,18 +312,18 @@ namespace UniversalEditor.Plugins.Multimedia3D.UserInterface.Editors.Model vertex_data = list.ToArray(); } - if (vaos != null) + if (vao != null) { - gla.Engine.DeleteVertexArray(vaos); + gla.Engine.DeleteVertexArray(vao); } // we need to create a VAO to store the other buffers - vaos = gla.Engine.CreateVertexArray(1); + vao = gla.Engine.CreateVertexArray(); // this is the VBO that holds the vertex data using (RenderBuffer buffer = gla.Engine.CreateBuffer()) { - vaos[0].Bind(); + vao.Bind(); buffer.Bind(BufferTarget.ArrayBuffer); buffer.SetData(vertex_data, BufferDataUsage.StaticDraw); @@ -320,7 +343,7 @@ namespace UniversalEditor.Plugins.Multimedia3D.UserInterface.Editors.Model // reset the state; we will re-enable the VAO when needed buffer.Unbind(); - vaos[0].Unbind(); // must be called BEFORE the buffer gets disposed + vao.Unbind(); // must be called BEFORE the buffer gets disposed } changed = false; } diff --git a/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/Audio/Waveform/WaveformAudioObjectModel.cs b/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/Audio/Waveform/WaveformAudioObjectModel.cs index 2da0f2fe..cb9fb7d8 100644 --- a/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/Audio/Waveform/WaveformAudioObjectModel.cs +++ b/Plugins/UniversalEditor.Plugins.Multimedia/ObjectModels/Multimedia/Audio/Waveform/WaveformAudioObjectModel.cs @@ -152,8 +152,8 @@ namespace UniversalEditor.ObjectModels.Multimedia.Audio.Waveform clone.Header.DataRate = this.Header.DataRate; clone.Header.FormatTag = this.Header.FormatTag; clone.Header.SampleRate = this.Header.SampleRate; - clone.RawData = (this.mvarRawData.Clone() as byte[]); - clone.RawSamples = (this.RawSamples.Clone() as WaveformAudioSamples); + clone.RawData = (this.RawData?.Clone() as byte[]); + clone.RawSamples = (this.RawSamples?.Clone() as WaveformAudioSamples); clone.Information.AlbumTitle = (Information.AlbumTitle.Clone() as string); clone.Information.Comments = (Information.Comments.Clone() as string); diff --git a/update.sh b/update.sh new file mode 100755 index 00000000..dcb0f8e6 --- /dev/null +++ b/update.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +GIT_USER=alcexhim +GIT_URL=git@github.com:$GIT_USER +GIT_PROJECTS="MBS.Audio MBS.Framework MBS.Framework.UserInterface MBS.Framework.Rendering UniversalEditor" + +for name in $GIT_PROJECTS; do + + if [ -d ../$name ]; then + cd ../$name && git pull + else + cd ../ && git clone $GIT_URL/$name + cd $name + fi + +done