浏览代码

Merge remote-tracking branch 'origin/frank' into meetings

Kenric Nugteren 2 年之前
父节点
当前提交
727d647b30

+ 1 - 1
InABox.Core/AutoEntity/AutoEntityUnionGenerator.cs

@@ -50,7 +50,7 @@ namespace InABox.Core
             Filter = filter;
         }
         
-        public AutoEntityUnionTable<TInterface, TEntity> AddConstant<TType>(TType constant, Expression<Func<TInterface, object?>> mapping)
+        public AutoEntityUnionTable<TInterface, TEntity> AddConstant<TType>(Expression<Func<TInterface, object?>> mapping, TType constant)
         {
             _constants.Add(new AutoEntityUnionConstant(constant, new Column<TInterface>(mapping)));
             return this;

+ 0 - 46
InABox.Core/Classes/CoreTime.cs

@@ -1,46 +0,0 @@
-using System;
-
-namespace InABox.Core
-{
-    public class CoreTime : BaseObject, IEnclosedEntity
-    {
-        [TimeOfDayEditor]
-        [EditorSequence(1)]
-        [LoggableProperty(Format = "HH\\:mm")]
-        public TimeSpan Start { get; set; }
-        
-        [DurationEditor(Summary = Summary.Sum)]
-        [EditorSequence(2)]
-        public TimeSpan Duration { get; set; }
-        
-        [TimeOfDayEditor]
-        [EditorSequence(3)]
-        [LoggableProperty(Format = "HH\\:mm")]
-        public TimeSpan Finish { get; set; }
-
-
-        private bool bChanging = false;
-        
-        protected override void DoPropertyChanged(string name, object? before, object? after)
-        {
-            base.DoPropertyChanged(name, before, after);
-            
-            if (bChanging)
-                return;
-            bChanging = true;
-            
-            if (String.Equals(name,nameof(Start)))
-                Duration = Finish > (TimeSpan)after ? Finish.Subtract((TimeSpan)after) : new TimeSpan();
-
-            else if (String.Equals(name,nameof(Finish)))
-                Duration = (TimeSpan)after > Start ? ((TimeSpan)after).Subtract(Start) : new TimeSpan();
-            
-            else if (String.Equals(name,nameof(Duration)))
-                Finish = Start.Add((TimeSpan)after);
-            
-            bChanging = false;
-            
-        }
-        
-    }
-}

+ 0 - 14
InABox.Core/Editors/CoreTimeEditor.cs

@@ -1,14 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace InABox.Core
-{
-    public class CoreTimeEditor : BaseEditor
-    {
-        protected override BaseEditor DoClone()
-        {
-            return new CoreTimeEditor();
-        }
-    }
-}

+ 3 - 20
InABox.Core/DateTimeExtensions.cs → InABox.Core/Utils/DateTimeExtensions.cs

@@ -4,31 +4,19 @@ namespace InABox.Core
 {
     public static class DateTimeExtensions
     {
+        
         public static DateTime Floor(this DateTime dateTime, TimeSpan interval)
         {
             return dateTime.AddTicks(-(dateTime.Ticks % interval.Ticks));
         }
-
-        public static TimeSpan Floor(this TimeSpan timespan, TimeSpan interval)
-        {
-            return timespan.Subtract(new TimeSpan(timespan.Ticks % interval.Ticks));
-        }
-
+        
         public static DateTime Ceiling(this DateTime dateTime, TimeSpan interval)
         {
             var overflow = dateTime.Ticks % interval.Ticks;
 
             return overflow == 0 ? dateTime : dateTime.AddTicks(interval.Ticks - overflow);
         }
-
-        public static TimeSpan Ceiling(this TimeSpan timespan, TimeSpan interval)
-        {
-            var overflow = timespan.Ticks % interval.Ticks;
-
-            return overflow == 0 ? timespan : timespan.Add(new TimeSpan(interval.Ticks - overflow));
-        }
-
-
+        
         public static DateTime Round(this DateTime dateTime, TimeSpan interval)
         {
             var halfIntervalTicks = (interval.Ticks + 1) >> 1;
@@ -36,11 +24,6 @@ namespace InABox.Core
             return dateTime.AddTicks(halfIntervalTicks - (dateTime.Ticks + halfIntervalTicks) % interval.Ticks);
         }
 
-        public static TimeSpan Round(this TimeSpan timespan, TimeSpan interval)
-        {
-            var halfIntervalTicks = (interval.Ticks + 1) >> 1;
 
-            return timespan.Add(new TimeSpan(halfIntervalTicks - (timespan.Ticks + halfIntervalTicks) % interval.Ticks));
-        }
     }
 }

+ 28 - 0
InABox.Core/Utils/TimeSpanExtensions.cs

@@ -0,0 +1,28 @@
+using System;
+
+namespace InABox.Core
+{
+    
+    public static class TimeExtensions
+    {
+        public static TimeSpan Floor(this TimeSpan timespan, TimeSpan interval)
+        {
+            return timespan.Subtract(new TimeSpan(timespan.Ticks % interval.Ticks));
+        }
+        
+        public static TimeSpan Ceiling(this TimeSpan timespan, TimeSpan interval)
+        {
+            var overflow = timespan.Ticks % interval.Ticks;
+
+            return overflow == 0 ? timespan : timespan.Add(new TimeSpan(interval.Ticks - overflow));
+        }
+        
+        public static TimeSpan Round(this TimeSpan timespan, TimeSpan interval)
+        {
+            var halfIntervalTicks = (interval.Ticks + 1) >> 1;
+
+            return timespan.Add(new TimeSpan(halfIntervalTicks - (timespan.Ticks + halfIntervalTicks) % interval.Ticks));
+        }
+    }
+
+}

+ 2 - 0
inabox.database.sqlite/SQLiteProvider.cs

@@ -1333,6 +1333,8 @@ namespace InABox.Database.SQLite
                 return string.Format("\'" + "{0}" + "\'", value.ToString()?.Replace("\'", "\'\'"));
             if (value is string[])
                 return string.Format("hex({0})", BitConverter.ToString(Encoding.ASCII.GetBytes(value.ToString() ?? "")).Replace("-", string.Empty));
+            if (value is IColumn col)
+                return $"[{col.Property}]";
             return value.ToString() ?? "";
 
         }

+ 12 - 1
inabox.wpf/DynamicGrid/DynamicEditorGrid.xaml.cs

@@ -41,6 +41,16 @@ namespace InABox.DynamicGrid
         private Type? LayoutType;
         private DynamicEditorGridLayout? Layout;
 
+        public bool TabStripVisible
+        {
+            get { return Layout != null ? Layout.TabStripVisible : false; }
+            set
+            {
+                if (Layout != null) 
+                    Layout.TabStripVisible = value;
+            }
+        }
+
         public DynamicEditorGrid()
         {
             InitializeComponent();
@@ -410,9 +420,10 @@ namespace InABox.DynamicGrid
                         var entityValue = EditorGrid.GetPropertyValue(column);
                         if (!Equals(editorValue, entityValue))
                         {
+                            bool bLoaded = editor.Loaded;
                             editor.Loaded = false;
                             editor.SetValue(column, entityValue);
-                            editor.Loaded = true;
+                            editor.Loaded = bLoaded;
                         }
                     }
                 }

+ 19 - 5
inabox.wpf/DynamicGrid/DynamicGrid.cs

@@ -2455,6 +2455,7 @@ namespace InABox.DynamicGrid
         {    
                 DoAdd();
         }
+        
         public virtual DynamicEditorPages LoadEditorPages(T item)
         {
             DynamicEditorPages pages = new DynamicEditorPages();
@@ -2485,16 +2486,18 @@ namespace InABox.DynamicGrid
         protected virtual void CustomiseEditorForm(IDynamicEditorForm form)
         {
         }
+        
+        public DynamicEditorPages Pages { get; private set; }
 
         public override void InitialiseEditorForm(IDynamicEditorForm editor, T[] items, Func<Type, CoreTable>? pageDataHandler = null, bool preloadPages = false)
         {
-            var pages = items.Length == 1 ? LoadEditorPages(items.First()) : new DynamicEditorPages();
+            Pages = items.Length == 1 ? LoadEditorPages(items.First()) : new DynamicEditorPages();
 
             var buttons = new DynamicEditorButtons();
             if (items.Length == 1)
                 LoadEditorButtons(items.First(), buttons);
 
-            editor.Setup(items.Any() ? items.First().GetType() : typeof(T), pages, buttons, pageDataHandler, preloadPages);
+            editor.Setup(items.Any() ? items.First().GetType() : typeof(T), Pages, buttons, pageDataHandler, preloadPages);
 
             editor.OnCustomiseColumns += (sender, columns) =>
             {
@@ -2539,8 +2542,8 @@ namespace InABox.DynamicGrid
                 try
                 {
                     using var Wait = new WaitCursor();
-
-                    OnBeforeSave?.Invoke(editor, items);
+                    DoBeforeSave(editor, items);
+                    
 
                     if (items.Length == 1)
                         editor.UnloadEditorPages(false);
@@ -2548,8 +2551,9 @@ namespace InABox.DynamicGrid
                         SaveItem(item);
                     if (items.Length == 1)
                         editor.UnloadEditorPages(true);
+                    
+                    DoAfterSave(editor, items);
 
-                    OnAfterSave?.Invoke(editor, items);
                 }
                 catch (Exception err)
                 {
@@ -2564,6 +2568,16 @@ namespace InABox.DynamicGrid
             AfterLoad(editor, items);
         }
 
+        protected virtual void DoAfterSave(IDynamicEditorForm editor, T[] items)
+        {
+            OnAfterSave?.Invoke(editor, items);
+        }
+
+        protected virtual void DoBeforeSave(IDynamicEditorForm editor, T[] items)
+        {
+            OnBeforeSave?.Invoke(editor, items);
+        }
+
         public override bool EditItems(T[] items, Func<Type, CoreTable>? PageDataHandler = null, bool PreloadPages = false)
         {
             DynamicEditorForm editor;

+ 15 - 0
inabox.wpf/DynamicGrid/DynamicTabControl.cs

@@ -107,6 +107,21 @@ namespace InABox.DynamicGrid
         {
             return new DynamicTabItem();
         }
+
+        public static readonly DependencyProperty TabStripVisibleProperty =
+            DependencyProperty.Register(nameof(TabStripVisible), typeof(bool), typeof(DynamicTabControl), new PropertyMetadata(true));
+
+        public bool TabStripVisible
+        {
+            get => (bool)GetValue(TabStripVisibleProperty);
+            set
+            {
+                SetValue(TabStripVisibleProperty, value);
+                Style s = new Style();
+                s.Setters.Add(new Setter(UIElement.VisibilityProperty, value ? Visibility.Visible : Visibility.Collapsed));
+                ItemContainerStyle = s;
+            }
+        }
     }
     
     public class DynamicTabItem : TabItem

+ 1 - 1
inabox.wpf/DynamicGrid/DynamicTreeView.cs

@@ -152,7 +152,7 @@ namespace InABox.DynamicGrid
         protected abstract Expression<Func<T, Guid>> ParentID { get; }
         protected abstract Expression<Func<T, String>> Description { get; }
 
-        protected CoreTable Data { get; private set; }
+        public CoreTable Data { get; private set; }
 
         private ContextMenu _menu;
         private SfTreeGrid _tree;

+ 0 - 413
inabox.wpf/DynamicGrid/Editors/CoreTimeEditor/CoreTimeEditorControl.cs

@@ -1,413 +0,0 @@
-using InABox.Core;
-using Syncfusion.Windows.Shared;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Input;
-using System.Windows.Media;
-
-namespace InABox.DynamicGrid
-{
-    public class CoreTimeEditorControl : DynamicEnclosedEditorControl<CoreTime, CoreTimeEditor>
-    {
-        
-        static CoreTimeEditorControl()
-        {
-            //DynamicEditorControlFactory.Register<CoreTimeEditorControl, CoreTimeEditor>();
-        }
-        
-        private Grid Grid;
-
-        private DateTimeEdit Start;
-        private TimeSpanEdit Duration;
-        private DateTimeEdit Finish;
-
-        private CoreTime Time = new();
-
-        public override void Configure()
-        {
-        }
-
-        protected override FrameworkElement CreateEditor()
-        {
-            Grid = new Grid();
-
-            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
-            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
-            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
-            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
-
-            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
-            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
-            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
-            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
-
-            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
-            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
-            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
-            Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
-
-            Start = CreateTimeEdit("Start:", 0, StartChanged, false);
-            Duration = CreateTimeSpanEdit("Duration:", 4, DurationChanged, true);
-            Finish = CreateTimeEdit("Finish:", 8, FinishChanged, true);
-            
-            return Grid;
-        }
-
-        private void StartChanged(TimeSpan start)
-        {
-            Time.Start = start;
-
-            UpdateEditors();
-        }
-
-        private void DurationChanged(TimeSpan duration)
-        {
-            Time.Duration = duration;
-
-            UpdateEditors();
-        }
-
-        private void FinishChanged(TimeSpan finish)
-        {
-            Time.Finish = finish;
-
-            UpdateEditors();
-        }
-
-        private void UpdateEditors()
-        {
-            SetValue(Start, Time.Start);
-            SetValue(Duration, Time.Duration);
-            SetValue(Finish, Time.Finish);
-
-            CheckChanged();
-        }
-
-        private TimeSpanEdit CreateTimeSpanEdit(string header, int column, Action<TimeSpan> onChanged, bool leftMargin)
-        {
-            var label = new Label
-            {
-                Content = header,
-                Margin = new Thickness(leftMargin ? 5 : 0, 0, 0, 0)
-            };
-            label.SetValue(Grid.ColumnProperty, column);
-
-            var edit = new TimeSpanEdit
-            {
-                Format = "h:mm",
-                MinValue = new TimeSpan(),
-                MaxValue = TimeSpan.MaxValue,
-                VerticalAlignment = VerticalAlignment.Stretch,
-                VerticalContentAlignment = VerticalAlignment.Center,
-                HorizontalAlignment = HorizontalAlignment.Stretch,
-                HorizontalContentAlignment = HorizontalAlignment.Center,
-                ShowArrowButtons = false
-            };
-            edit.SetValue(Grid.ColumnProperty, column + 1);
-
-            edit.PreviewKeyDown += (o, e) =>
-            {
-                var separator = edit.Text.IndexOf(":");
-
-                if (e.Key == Key.OemPeriod)
-                {
-                    edit.Select(separator + 1, 2);
-                    e.Handled = true;
-                }
-                else if (e.Key == Key.Back)
-                {
-                    if (string.Equals(edit.SelectedText, "00"))
-                        edit.Select(0, separator);
-                    else
-                        edit.SelectedText = "00";
-                    e.Handled = true;
-                }
-                else if (e.Key == Key.Tab)
-                {
-                    if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.LeftShift))
-                    {
-                        if (edit.SelectionStart > separator)
-                        {
-                            edit.Select(0, separator);
-                            e.Handled = true;
-                        }
-                    }
-                    else
-                    {
-                        if (edit.SelectionLength != edit.Text.Length && edit.SelectionStart < separator)
-                        {
-                            edit.Select(separator + 1, 2);
-                            e.Handled = true;
-                        }
-                    }
-                }
-            };
-
-            var changed = false;
-            edit.ValueChanged += (o, e) =>
-            {
-                changed = true;
-            };
-
-            edit.LostFocus += (o, e) =>
-            {
-                if (changed)
-                    onChanged(GetValue(edit));
-            };
-
-            var less = new Button
-            {
-                Content = "<",
-                Width = 23,
-                Margin = new Thickness(2, 0, 0, 0),
-                Focusable = false
-            };
-            less.SetValue(Grid.ColumnProperty, column + 2);
-
-            less.Click += (o, e) =>
-            {
-                edit.Value = edit.Value.HasValue && edit.Value >= new TimeSpan(0, 15, 0)
-                    ? edit.Value.Value.Subtract(new TimeSpan(0, 15, 0))
-                    : new TimeSpan(0);
-                onChanged(GetValue(edit));
-            };
-
-            var more = new Button
-            {
-                Content = ">",
-                Width = 23,
-                Margin = new Thickness(2, 0, 0, 0),
-                Focusable = false
-            };
-            more.SetValue(Grid.ColumnProperty, column + 3);
-
-            more.Click += (o, e) =>
-            {
-                edit.Value = edit.Value.HasValue ? edit.Value.Value.Add(new TimeSpan(0, 15, 0)) : new TimeSpan(0, 15, 0);
-                onChanged(GetValue(edit));
-            };
-
-            Grid.Children.Add(label);
-            Grid.Children.Add(more);
-            Grid.Children.Add(less);
-            Grid.Children.Add(edit);
-
-            return edit;
-        }
-
-        private DateTimeEdit CreateTimeEdit(string header, int column, Action<TimeSpan> onChanged, bool leftMargin)
-        {
-            var label = new Label
-            {
-                Content = header,
-                Margin = new Thickness(leftMargin ? 5 : 0, 0, 0, 0)
-            };
-            label.SetValue(Grid.ColumnProperty, column);
-
-            var edit = new DateTimeEdit
-            {
-                Pattern = DateTimePattern.CustomPattern,
-                CustomPattern = "HH:mm", //DateTimeFormat.Custom,
-                //FormatString = "HH:mm",
-                VerticalAlignment = VerticalAlignment.Stretch,
-                VerticalContentAlignment = VerticalAlignment.Center,
-                HorizontalAlignment = HorizontalAlignment.Stretch,
-                HorizontalContentAlignment = HorizontalAlignment.Center,
-                //TimeInterval = new TimeSpan(0, 15, 0),
-                //ShowButtonSpinner = false
-                DropDownView = DropDownViews.Clock,
-                IsButtonPopUpEnabled = false
-            };
-            edit.SetValue(Grid.ColumnProperty, column + 1);
-
-            edit.PreviewKeyDown += (o, e) =>
-            {
-                var separator = edit.Text.IndexOf(":");
-
-                if (e.Key == Key.OemPeriod)
-                {
-                    edit.Select(separator + 1, 2);
-                    e.Handled = true;
-                }
-                else if (e.Key == Key.Back)
-                {
-                    if (string.Equals(edit.SelectedText, "00"))
-                        edit.Select(0, separator);
-                    else
-                        edit.SelectedText = "00";
-                    e.Handled = true;
-                }
-                else if (e.Key == Key.Tab)
-                {
-                    if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.LeftShift))
-                    {
-                        if (edit.SelectionStart > separator)
-                        {
-                            edit.Select(0, separator);
-                            e.Handled = true;
-                        }
-                    }
-                    else
-                    {
-                        if (edit.SelectionLength != edit.Text.Length && edit.SelectionStart < separator)
-                        {
-                            edit.Select(separator + 1, 2);
-                            e.Handled = true;
-                        }
-                    }
-                }
-            };
-
-            var changed = false;
-            edit.DateTimeChanged += (o, e) =>
-            {
-                changed = true;
-            };
-
-            edit.LostFocus += (o, e) =>
-            {
-                if (changed)
-                {
-                    onChanged(GetValue(edit));
-                }
-            };
-
-            var less = new Button
-            {
-                Content = "<",
-                Width = 23,
-                Margin = new Thickness(2, 0, 0, 0),
-                Focusable = false
-            };
-            less.SetValue(Grid.ColumnProperty, column + 2);
-
-            less.Click += (o, e) =>
-            {
-                edit.DateTime = edit.DateTime.HasValue && edit.DateTime.Value.TimeOfDay >= new TimeSpan(0, 15, 0)
-                    ? edit.DateTime.Value.Subtract(new TimeSpan(0, 15, 0))
-                    : edit.DateTime;
-                onChanged(GetValue(edit));
-            };
-
-            var more = new Button
-            {
-                Content = ">",
-                Width = 23,
-                Margin = new Thickness(2, 0, 0, 0),
-                Focusable = false
-            };
-            more.SetValue(Grid.ColumnProperty, column + 3);
-
-            more.Click += (o, e) =>
-            {
-                edit.DateTime = edit.DateTime.HasValue && edit.DateTime.Value.TimeOfDay < new TimeSpan(23, 45, 0)
-                    ? edit.DateTime.Value.Add(new TimeSpan(0, 15, 0))
-                    : edit.DateTime;
-                onChanged(GetValue(edit));
-            };
-
-            Grid.Children.Add(label);
-            Grid.Children.Add(edit);
-            Grid.Children.Add(less);
-            Grid.Children.Add(more);
-
-            return edit;
-        }
-
-        private static TimeSpan GetValue(DateTimeEdit edit)
-        {
-            var result = new TimeSpan(0);
-
-            if (edit.DateTime.HasValue)
-                result = edit.DateTime.Value.TimeOfDay;
-
-            result = new TimeSpan(result.Hours, result.Minutes, 0);
-
-            return result;
-        }
-        private static void SetValue(DateTimeEdit edit, TimeSpan value)
-        {
-            if (value.Ticks > 0)
-                edit.DateTime = DateTime.MinValue.Add(value);
-            else
-                edit.DateTime = null;
-        }
-        private static TimeSpan GetValue(TimeSpanEdit edit)
-        {
-            var result = new TimeSpan(0);
-
-            if (edit.Value.HasValue)
-                result = edit.Value.Value;
-
-            return result;
-        }
-        private static void SetValue(TimeSpanEdit edit, TimeSpan value)
-        {
-            edit.Value = value;
-        }
-
-        public override int DesiredHeight()
-        {
-            return 25;
-        }
-
-        public override int DesiredWidth()
-        {
-            return int.MaxValue;
-        }
-
-        public override Dictionary<string, object?> GetValues()
-        {
-            return new Dictionary<string, object?>
-            {
-                { $"{ColumnName}.Start", Time.Start },
-                { $"{ColumnName}.Duration", Time.Duration },
-                { $"{ColumnName}.Finish", Time.Finish }
-            };
-        }
-
-        public override object? GetValue(string property)
-        {
-            if (!property.StartsWith($"{ColumnName}.")) return null;
-            property = property[(ColumnName.Length + 1)..];
-
-            if (property == "Start") return Time.Start;
-            if (property == "Duration") return Time.Duration;
-            if (property == "Finish") return Time.Finish;
-
-            return null;
-        }
-
-        public override void SetValue(string property, object? value)
-        {
-            if (!property.StartsWith($"{ColumnName}.")) return;
-            property = property[(ColumnName.Length + 1)..];
-
-            if (value is not TimeSpan timeSpan) return;
-
-            if (property == "Start") Time.Start = timeSpan;
-            else if (property == "Duration") Time.Duration = timeSpan;
-            else if (property == "Finish") Time.Finish = timeSpan;
-
-            UpdateEditors();
-        }
-
-        public override void SetColor(Color color)
-        {
-            Start.Background = new SolidColorBrush(color);
-            Duration.Background = new SolidColorBrush(color);
-            Finish.Background = new SolidColorBrush(color);
-        }
-
-        public override void SetFocus()
-        {
-            Start.Focus();
-        }
-    }
-}

+ 14 - 6
inabox.wpf/DynamicGrid/Editors/NotesEditor/NotesEditorControl.cs

@@ -6,6 +6,7 @@ using System.Windows.Data;
 using System.Windows.Media;
 using InABox.Clients;
 using InABox.Core;
+using InABox.WPF;
 
 namespace InABox.DynamicGrid
 {
@@ -106,6 +107,7 @@ namespace InABox.DynamicGrid
             Grid = new Grid();
             Grid.VerticalAlignment = VerticalAlignment.Stretch;
             Grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
+            Grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) });
             Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
             Grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) });
 
@@ -119,7 +121,9 @@ namespace InABox.DynamicGrid
                 //Background = new SolidColorBrush(Colors.Yellow)
             };
             Scroll.SetValue(Grid.RowProperty, 0);
+            Scroll.SetValue(Grid.RowSpanProperty, 2);
             Scroll.SetValue(Grid.ColumnProperty, 0);
+            Scroll.SetValue(Grid.ColumnSpanProperty, 2);
 
             Grid.Children.Add(Scroll);
 
@@ -156,21 +160,25 @@ namespace InABox.DynamicGrid
             };
 
             Scroll.Child = History;
-
+            
             Button = new Button
             {
                 VerticalAlignment = VerticalAlignment.Stretch,
                 VerticalContentAlignment = VerticalAlignment.Center,
                 HorizontalAlignment = HorizontalAlignment.Stretch,
                 HorizontalContentAlignment = HorizontalAlignment.Center,
-                Content = "Add",
-                Width = 50
+                BorderThickness = new Thickness(0F),
+                Background = Brushes.Transparent,
+                Content = new Image() { Source = Wpf.Resources.add.AsBitmapImage() },
+                Width = 48,
+                Height=48,
+                Margin=new Thickness(0,0,5,5)
             };
-            Button.SetValue(Grid.RowProperty, 0);
-            Button.SetValue(Grid.ColumnProperty, 1);
             Button.Click += Button_Click;
-            Button.Margin = new Thickness(5, 0, 0, 0);
+            Button.SetValue(Grid.RowProperty, 1);
+            Button.SetValue(Grid.ColumnProperty, 1);
             Grid.Children.Add(Button);
+
             return Grid;
         }
 

+ 1 - 1
inabox.wpf/DynamicGrid/EmbeddedDynamicEditorForm.xaml

@@ -16,7 +16,7 @@
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
             <RowDefinition Height="*" />
-            <RowDefinition Height="40" />
+            <RowDefinition Height="40" x:Name="ButtonRow"/>
         </Grid.RowDefinitions>
 
         <local:DynamicEditorGrid x:Name="Editor"

+ 57 - 0
inabox.wpf/DynamicGrid/EmbeddedDynamicEditorForm.xaml.cs

@@ -45,6 +45,55 @@ namespace InABox.DynamicGrid
         }
 
         public bool ReadOnly { get; set; }
+        
+        public static readonly DependencyProperty ButtonsVisibleProperty =
+            DependencyProperty.Register(
+                nameof(ButtonsVisible), 
+                typeof(bool), 
+                typeof(EmbeddedDynamicEditorForm), 
+                new UIPropertyMetadata(true)
+            );
+        
+        public bool ButtonsVisible
+        {
+            get => (bool)GetValue(ButtonsVisibleProperty);
+            set
+            {
+                SetValue(ButtonsVisibleProperty, value);
+                UpdateButtonsRowVisibility();
+            }
+        }
+        
+        private void UpdateButtonsRowVisibility()
+        {
+            ButtonRow.Height = ButtonsVisible
+                ? new GridLength(40, GridUnitType.Pixel)
+                : new GridLength(0, GridUnitType.Pixel);
+        }
+        
+        public static readonly DependencyProperty TabsVisibleProperty =
+            DependencyProperty.Register(
+                nameof(TabsVisible), 
+                typeof(bool), 
+                typeof(EmbeddedDynamicEditorForm), 
+                new UIPropertyMetadata(true)
+            );
+        
+        public bool TabsVisible
+        {
+            get => (bool)GetValue(TabsVisibleProperty);
+            set
+            {
+                SetValue(TabsVisibleProperty, value);
+                UpdateTabsVisibility();
+            }
+        }
+
+
+        private void UpdateTabsVisibility()
+        {
+            Editor.TabStripVisible = TabsVisible;
+        }
 
         #region Events
 
@@ -82,6 +131,14 @@ namespace InABox.DynamicGrid
         {
             InitializeComponent();
         }
+
+        public override void OnApplyTemplate()
+        {
+            base.OnApplyTemplate();
+            UpdateButtonsRowVisibility();
+            UpdateTabsVisibility();
+        }
+
         public EmbeddedDynamicEditorForm(Type type, DynamicEditorPages? pages = null, DynamicEditorButtons? buttons = null,
             Func<Type, CoreTable>? PageDataHandler = null, bool PreloadPages = false): this()
         {

+ 8 - 0
inabox.wpf/DynamicGrid/Layouts/DefaultDynamicEditorGridLayout.cs

@@ -10,6 +10,12 @@ namespace InABox.DynamicGrid
 {
     public class DefaultDynamicEditorGridLayout : DynamicEditorGridLayout
     {
+        public override bool TabStripVisible
+        {
+            get { return Details.TabStripVisible; }
+            set { Details.TabStripVisible = value; }
+        }
+
         private DynamicTabControl Details;
 
         public DefaultDynamicEditorGridLayout()
@@ -34,6 +40,8 @@ namespace InABox.DynamicGrid
                 tab.Content = page;
                 Details.Items.Add(tab);
             }
+
+            Details.SelectedItem = Details.Items.Count > 0 ? Details.Items[0] : null;
         }
 
         private bool bChanging;

+ 2 - 0
inabox.wpf/DynamicGrid/Layouts/DynamicEditorGridLayout.cs

@@ -11,6 +11,8 @@ namespace InABox.DynamicGrid
     public abstract class DynamicEditorGridLayout : ContentControl
     {
 
+        public abstract bool TabStripVisible { get; set; }
+        
         public delegate void SelectPageHandler(IDynamicEditorPage page);
 
         public event SelectPageHandler? OnSelectPage;

+ 9 - 0
inabox.wpf/DynamicGrid/Layouts/VerticalDynamicEditorGridLayout.xaml.cs

@@ -20,6 +20,13 @@ namespace InABox.DynamicGrid
     /// </summary>
     public partial class VerticalDynamicEditorGridLayout : DynamicEditorGridLayout
     {
+        
+        public override bool TabStripVisible
+        {
+            get { return Editors.TabStripVisible; }
+            set { Editors.TabStripVisible = value; }
+        }
+        
         public VerticalDynamicEditorGridLayout()
         {
             InitializeComponent();
@@ -44,6 +51,8 @@ namespace InABox.DynamicGrid
                     OtherPages.Items.Add(tab);
                 }
             }
+
+            Editors.SelectedIndex = 0;
         }
 
         private bool bChanging;

+ 54 - 11
inabox.wpf/Themes/Generic.xaml

@@ -477,17 +477,60 @@
                             <Setter TargetName="AddButton" Property="Visibility" Value="Collapsed" />
                         </Trigger>
 
-                        <Trigger Property="TabStripPlacement" Value="{x:Static Dock.Top}">
-                            <Setter TargetName="Panel" Property="Grid.Row" Value="0" />
-                            <Setter TargetName="Content" Property="BorderThickness" Value="0,0.75,0,0" />
-                            <Setter TargetName="Content" Property="Padding" Value="0,2,0,0" />
-                        </Trigger>
-
-                        <Trigger Property="TabStripPlacement" Value="{x:Static Dock.Bottom}">
-                            <Setter TargetName="Panel" Property="Grid.Row" Value="2" />
-                            <Setter TargetName="Content" Property="BorderThickness" Value="0,0,0,0.75" />
-                            <Setter TargetName="Content" Property="Padding" Value="0,0,0,3" />
-                        </Trigger>
+                        <!-- <Trigger Property="TabStripPlacement" Value="{x:Static Dock.Top}"> -->
+                        <!--     <Setter TargetName="Panel" Property="Grid.Row" Value="0" /> -->
+                        <!--     <Setter TargetName="Content" Property="BorderThickness" Value="0,0.75,0,0" /> -->
+                        <!--     <Setter TargetName="Content" Property="Padding" Value="0,2,0,0" /> -->
+                        <!-- </Trigger> -->
+                        
+                        <MultiTrigger>
+                            <MultiTrigger.Conditions>
+                                <Condition Property="TabStripPlacement" Value="{x:Static Dock.Top}" />
+                                <Condition Property="TabStripVisible" Value="False"/>
+                            </MultiTrigger.Conditions>
+                            <MultiTrigger.Setters>
+                                <Setter TargetName="Panel" Property="Grid.Row" Value="0" />
+                                <Setter TargetName="Content" Property="BorderThickness" Value="0,0,0,0" />
+                                <Setter TargetName="Content" Property="Padding" Value="0,0,0,0" />                        
+                            </MultiTrigger.Setters>
+                        </MultiTrigger>
+                        
+                        <MultiTrigger>
+                            <MultiTrigger.Conditions>
+                                <Condition Property="TabStripPlacement" Value="{x:Static Dock.Top}" />
+                                <Condition Property="TabStripVisible" Value="True"/>
+                            </MultiTrigger.Conditions>
+                            <MultiTrigger.Setters>
+                                <Setter TargetName="Panel" Property="Grid.Row" Value="0" />
+                                <Setter TargetName="Content" Property="BorderThickness" Value="0,0.75,0,0" />
+                                <Setter TargetName="Content" Property="Padding" Value="0,2,0,0" />                        
+                            </MultiTrigger.Setters>
+                        </MultiTrigger>
+                        
+                        <MultiTrigger>
+                            <MultiTrigger.Conditions>
+                                <Condition Property="TabStripPlacement" Value="{x:Static Dock.Bottom}" />
+                                <Condition Property="TabStripVisible" Value="False"/>
+                            </MultiTrigger.Conditions>
+                            <MultiTrigger.Setters>
+                                <Setter TargetName="Panel" Property="Grid.Row" Value="2" />
+                                <Setter TargetName="Content" Property="BorderThickness" Value="0,0,0,0" />
+                                <Setter TargetName="Content" Property="Padding" Value="0,0,0,0" />                           
+                            </MultiTrigger.Setters>
+                        </MultiTrigger>
+
+                        <MultiTrigger>
+                            <MultiTrigger.Conditions>
+                                <Condition Property="TabStripPlacement" Value="{x:Static Dock.Bottom}" />
+                                <Condition Property="TabStripVisible" Value="True"/>
+                            </MultiTrigger.Conditions>
+                            <MultiTrigger.Setters>
+                                <Setter TargetName="Panel" Property="Grid.Row" Value="2" />
+                                <Setter TargetName="Content" Property="BorderThickness" Value="0,0,0,0.75" />
+                                <Setter TargetName="Content" Property="Padding" Value="0,0,0,3" />                           
+                            </MultiTrigger.Setters>
+                        </MultiTrigger>
+                        
 
 
                     </ControlTemplate.Triggers>