diff --git a/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Palette/PaletteEditor.uexml b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Palette/PaletteEditor.uexml index ba51bbf3..26abb13e 100644 --- a/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Palette/PaletteEditor.uexml +++ b/Content/UniversalEditor.Content.PlatformIndependent/Editors/Multimedia/Palette/PaletteEditor.uexml @@ -3,10 +3,11 @@ - + - + + @@ -15,8 +16,12 @@ + + - + + + diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Controls/ColorPalette/ColorPaletteControl.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Controls/ColorPalette/ColorPaletteControl.cs new file mode 100644 index 00000000..3575158c --- /dev/null +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Controls/ColorPalette/ColorPaletteControl.cs @@ -0,0 +1,178 @@ +// +// ColorPaletteControl.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.Drawing; +using MBS.Framework.UserInterface; +using MBS.Framework.UserInterface.Drawing; +using MBS.Framework.UserInterface.Input.Mouse; +using UniversalEditor.ObjectModels.Multimedia.Palette; + +namespace UniversalEditor.Plugins.Multimedia.UserInterface.Controls.ColorPalette +{ + public class ColorPaletteControl : CustomControl + { + public event EventHandler SelectionChanged; + protected virtual void OnSelectionChanged(EventArgs e) + { + SelectionChanged?.Invoke(this, e); + } + + public PaletteEntry.PaletteEntryCollection Entries { get; set; } = new PaletteEntry.PaletteEntryCollection(); + + public Dimension2D PaletteEntrySize { get; set; } = new Dimension2D(64, 24); + public double ZoomFactor { get; set; } = 1.0; + + private int GetLineWidth() + { + return (int)((double)Size.Width / (PaletteEntrySize.Width * ZoomFactor)); + } + + + public PaletteEntry HitTest(Vector2D location) + { + int x = 0, y = 0, w = (int)(PaletteEntrySize.Width * ZoomFactor), h = (int)(PaletteEntrySize.Height * ZoomFactor); + y = (int)VerticalAdjustment.Value; + + + int startIndex = (int)(VerticalAdjustment.Value / h) * GetLineWidth(), endIndex = Entries.Count - 1; + int startLine = startIndex / w; + y = (int)VerticalAdjustment.Value; + + int zcount = 0; + for (int i = startIndex; i <= endIndex; i++) + { + if (x > (int)(Size.Width - w)) + { + x = 0; + y += h; + } + + Rectangle rect = new Rectangle(x + paletteSpacingX, y + paletteSpacingY, w - paletteSpacingX - paletteSpacingX, h - paletteSpacingY - paletteSpacingY); + + if (rect.Contains(location)) + return Entries[i]; + + x += w; + } + return null; + } + public PaletteEntry HitTest(double x, double y) + { + return HitTest(new Vector2D(x, y)); + } + + protected override void OnMouseDown(MouseEventArgs e) + { + base.OnMouseDown(e); + Focus(); + + PaletteEntry entry = HitTest(e.Location); + SelectedEntry = entry; + } + + protected override void OnPaint(PaintEventArgs e) + { + base.OnPaint(e); + + int x = 0, y = 0, w = (int)(PaletteEntrySize.Width * ZoomFactor), h = (int)(PaletteEntrySize.Height * ZoomFactor); + + double shscrh = Entries.Count / GetLineWidth(); + ScrollBounds = new Dimension2D(0, (shscrh * h) + h); + + int startIndex = (int)(VerticalAdjustment.Value / h) * GetLineWidth(), endIndex = Entries.Count - 1; + int startLine = startIndex / w; + y = (int)VerticalAdjustment.Value; + + int zcount = 0; + for (int i = startIndex; i <= endIndex; i++) + { + if (x > (int)(Size.Width - w)) + { + x = 0; + y += h; + } + + if (y > (int)(VerticalAdjustment.Value + Size.Height + h + h)) + { + // we're done for now + return; + } + + Rectangle rect = new Rectangle(x + paletteSpacingX, y + paletteSpacingY, w - paletteSpacingX - paletteSpacingX, h - paletteSpacingY - paletteSpacingY); + + PaletteEntry entry = Entries[i]; + if (entry.Color.A < 1.0) + { + // only fill the alpha background if we need to + DrawAlphaBackground(e.Graphics, rect); + } + e.Graphics.FillRectangle(new SolidBrush(entry.Color), rect); + if (entry == SelectedEntry) + { + e.Graphics.DrawRectangle(new Pen(SystemColors.HighlightBackground, new Measurement(2, MeasurementUnit.Pixel)), new Rectangle(x, y, w, h)); + } + zcount++; + x += w; + } + } + private TextureBrush AlphaBackgroundBrush = null; + private void DrawAlphaBackground(Graphics g, Rectangle rect) + { + // this is too slow for now, do absolutely nothing + return; + + /* + if (AlphaBackgroundBrush == null) + { + Image AlphaBackgroundImage = Image.Create(24, 24); + Graphics g = Graphics.FromImage(AlphaBackgroundImage); + g.FillRectangle(Brushes.White, new Rectangle(0, 0, 24, 24)); + g.FillRectangle(Brushes.Black, new Rectangle(16, 16, 16, 16)); + + AlphaBackgroundBrush = new TextureBrush(AlphaBackgroundImage); + } + */ + int qs = 0; + for (int patternY = 0; patternY < rect.Height; patternY += 8) + { + for (int patternX = qs; patternX < rect.Width - qs; patternX += 8) + { + g.FillRectangle(Brushes.Black, new Rectangle(rect.X + patternX, rect.Y + patternY, 4, 4)); + } + if (qs == 0) + { + qs = 8; + } + else + { + qs = 0; + } + } + // e.Graphics.FillRectangle(AlphaBackgroundBrush, rect); + } + + int paletteSpacingX = 2; + int paletteSpacingY = 2; + + private PaletteEntry _SelectedEntry = null; + public PaletteEntry SelectedEntry { get { return _SelectedEntry; } set { bool changed = (_SelectedEntry != value); _SelectedEntry = value; if (changed) { Refresh(); OnSelectionChanged(EventArgs.Empty); } } } + } +} diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/Dialogs/CalculateNeighboringColorsDialog.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/Dialogs/CalculateNeighboringColorsDialog.cs new file mode 100644 index 00000000..ea2c9c4d --- /dev/null +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/Dialogs/CalculateNeighboringColorsDialog.cs @@ -0,0 +1,107 @@ +// +// CalculateNeighboringColorsDialog.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 System.Collections.Generic; +using MBS.Framework.Drawing; +using MBS.Framework.UserInterface; +using MBS.Framework.UserInterface.Controls; +using UniversalEditor.ObjectModels.Multimedia.Palette; + +namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Palette.Dialogs +{ + [ContainerLayout(typeof(CalculateNeighboringColorsDialog), "UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Palette.Dialogs.CalculateNeighboringColorsDialog.glade")] + public class CalculateNeighboringColorsDialog : CustomDialog + { + private Button cmdOK; + private Controls.ColorPalette.ColorPaletteControl cc; + private ComboBox cboMode; + + public Color SelectedColor { get; set; } = Color.Empty; + public Color[] Colors { get; private set; } = new Color[0]; + + [EventHandler(nameof(cboMode), nameof(ComboBox.Changed))] + private void cboMode_Changed(object sender, EventArgs e) + { + cc.Entries.Clear(); + + Color[] colors = new Color[5]; + for (int i = 0; i < colors.Length; i++) + { + colors[i] = (Color)SelectedColor.Clone(); + } + + int selectedIndex = (cboMode.Model as DefaultTreeModel).Rows.IndexOf(cboMode.SelectedItem); + switch (selectedIndex) + { + case 0: // analogous + { + double hue = colors[2].GetHueScaled(360.0); + + // hsv in GIMP is 0.0-360.0, 0.0-100.0, and 0.0-100.0, so that's what we'll use + colors[0].Saturation -= 0.05; + colors[0].SetHueScaled(hue + 32, 360.0); + colors[1].Saturation -= 0.05; + colors[1].SetHueScaled(hue + 16, 360.0); + + colors[3].Saturation -= 0.05; + colors[3].SetHueScaled(hue - 16, 360.0); + colors[4].Saturation -= 0.05; + colors[4].SetHueScaled(hue - 32, 360.0); + break; + } + case 8: // shades + { + colors[0].Saturation = 0.65; + colors[1].Saturation = 0.40; + colors[2].Saturation = 0.90; + colors[3].Saturation = 0.95; + colors[4].Saturation = 0.80; + break; + } + } + + cc.Entries.Clear(); + for (int i = 0; i < colors.Length; i++) + { + cc.Entries.Add(colors[i]); + } + cc.Refresh(); + } + + protected override void OnCreated(EventArgs e) + { + base.OnCreated(e); + DefaultButton = cmdOK; + } + + [EventHandler(nameof(cmdOK), nameof(Control.Click))] + private void cmdOK_Click(object sender, EventArgs e) + { + List list = new List(); + for (int i = 0; i < cc.Entries.Count; i++) + { + list.Add(cc.Entries[i].Color); + } + Colors = list.ToArray(); + } + + } +} diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/Dialogs/CalculateNeighboringColorsDialog.glade b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/Dialogs/CalculateNeighboringColorsDialog.glade new file mode 100644 index 00000000..df5b74f3 --- /dev/null +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/Dialogs/CalculateNeighboringColorsDialog.glade @@ -0,0 +1,163 @@ + + + + + + + + + + + + Analogous + + + Monochromatic + + + Triadic + + + Complementary + + + Split complementary + + + Double split complementary + + + Square + + + Compound + + + Shades + + + + + False + Calculate Neighboring Colors + dialog + + + + + + False + vertical + 2 + + + False + end + + + gtk-ok + True + True + True + True + + + + True + True + 0 + + + + + gtk-cancel + True + True + True + True + + + True + True + 1 + + + + + False + False + 0 + + + + + True + False + vertical + + + True + False + + + True + False + _Mode + True + 0 + + + 0 + 0 + + + + + True + False + True + tmMode + + + 1 + 0 + + + + + False + True + 0 + + + + + UniversalEditor.Plugins.Multimedia.UserInterface.Controls.ColorPalette.ColorPaletteControl + True + False + + + True + True + 1 + + + + + + + + False + True + 1 + + + + + + cmdOK + + + diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/PaletteEditor.Designer.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/PaletteEditor.Designer.cs deleted file mode 100644 index 426a26d5..00000000 --- a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/PaletteEditor.Designer.cs +++ /dev/null @@ -1,65 +0,0 @@ -// -// PaletteEditor.Designer.cs - UWT designer initialization for PaletteEditor -// -// Author: -// Mike Becker -// -// Copyright (c) 2019-2020 Mike Becker -// -// 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 MBS.Framework.UserInterface; -using MBS.Framework.UserInterface.Controls; -using MBS.Framework.UserInterface.Layouts; - -namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Palette -{ - partial class PaletteEditor - { - private CustomControl cc = null; - private Container cInfo = null; - private TextBox txtColorName = null; - - /// - /// UWT designer initialization for . - /// - /// - /// UWT designer initialization in code is deprecated; continue improving the cross-platform Glade XML parser for ! - /// - private void InitializeComponent() - { - this.Layout = new BoxLayout(Orientation.Vertical); - - cc = new CustomControl(); - cc.MouseDown += cc_MouseDown; - cc.MouseDoubleClick += cc_MouseDoubleClick; - cc.KeyDown += cc_KeyDown; - cc.Paint += cc_Paint; - this.Controls.Add(cc, new BoxLayout.Constraints(true, true)); - - cInfo = new Container(); - cInfo.Layout = new BoxLayout(Orientation.Vertical); - this.Controls.Add(cInfo, new BoxLayout.Constraints(false, false)); - - Context.AttachCommandEventHandler("PaletteEditor_ContextMenu_Add", PaletteEditor_ContextMenu_Add_Click); - Context.AttachCommandEventHandler("PaletteEditor_ContextMenu_Change", PaletteEditor_ContextMenu_Change_Click); - Context.AttachCommandEventHandler("PaletteEditor_ContextMenu_Delete", PaletteEditor_ContextMenu_Delete_Click); - - txtColorName = new TextBox(); - txtColorName.KeyDown += txtColorName_KeyDown; - cInfo.Controls.Add(txtColorName, new BoxLayout.Constraints(false, true)); - } - - } -} diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/PaletteEditor.cs b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/PaletteEditor.cs index a9125ba0..8125c46c 100644 --- a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/PaletteEditor.cs +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/PaletteEditor.cs @@ -20,23 +20,97 @@ // along with this program. If not, see . using System; - +using System.Collections.Specialized; using MBS.Framework.Drawing; using MBS.Framework.UserInterface; +using MBS.Framework.UserInterface.Controls; using MBS.Framework.UserInterface.Dialogs; using MBS.Framework.UserInterface.Drawing; using MBS.Framework.UserInterface.Input.Keyboard; using UniversalEditor.ObjectModels.Multimedia.Palette; +using UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Palette.Dialogs; using UniversalEditor.UserInterface; +using UniversalEditor.UserInterface.Panels; namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Palette { /// /// Provides a UWT-based for a . /// - public partial class PaletteEditor : Editor + [ContainerLayout(typeof(PaletteEditor), "UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Palette.PaletteEditor.glade")] + public class PaletteEditor : Editor { + private Toolbar tb; + private Container pnlNoColors; + private Controls.ColorPalette.ColorPaletteControl cc; + private Container pnlColorInfo; + private TextBox txtColorName; + private Button cmdAddColor; + + protected override void OnCreated(EventArgs e) + { + base.OnCreated(e); + + Context.AttachCommandEventHandler("PaletteEditor_ContextMenu_Add", PaletteEditor_ContextMenu_Add_Click); + Context.AttachCommandEventHandler("PaletteEditor_ContextMenu_Change", PaletteEditor_ContextMenu_Change_Click); + Context.AttachCommandEventHandler("PaletteEditor_ContextMenu_Delete", PaletteEditor_ContextMenu_Delete_Click); + Context.AttachCommandEventHandler("PaletteEditor_CalculateNeighboringColors", PaletteEditor_CalculateNeighboringColors_Click); + + cc.Visible = false; + pnlNoColors.Visible = true; + pnlColorInfo.Visible = false; + + (tb.Items["tsbColorAdd"] as ToolbarItemButton).Click += tsbColorAdd_Click; + (tb.Items["tsbColorEdit"] as ToolbarItemButton).Click += tsbColorEdit_Click; + (tb.Items["tsbColorRemove"] as ToolbarItemButton).Click += tsbColorRemove_Click; + + ContextMenuCommandID = "PaletteEditor_ContextMenu_Unselected"; + + OnObjectModelChanged(e); + } + + private void PaletteEditor_CalculateNeighboringColors_Click(object sender, EventArgs e) + { + if (SelectedEntry == null) + { + MessageDialog.ShowDialog("Please select a palette entry.", "Error", MessageDialogButtons.OK, MessageDialogIcon.Error); + return; + } + + PaletteObjectModel palette = (ObjectModel as PaletteObjectModel); + if (palette == null) return; + + CalculateNeighboringColorsDialog dlg = new CalculateNeighboringColorsDialog(); + dlg.SelectedColor = SelectedEntry.Color; + if (dlg.ShowDialog() == DialogResult.OK) + { + int index = palette.Entries.IndexOf(SelectedEntry); + + for (int i = 0; i < dlg.Colors.Length; i++) + { + PaletteEntry entry = new PaletteEntry(); + entry.Color = dlg.Colors[i]; + + palette.Entries.Insert(index, entry); + cc.Entries.Insert(index, entry); + } + } + } + + private void tsbColorAdd_Click(object sender, EventArgs e) + { + PaletteEditor_ContextMenu_Add_Click(sender, e); + } + private void tsbColorEdit_Click(object sender, EventArgs e) + { + PaletteEditor_ContextMenu_Change_Click(sender, e); + } + private void tsbColorRemove_Click(object sender, EventArgs e) + { + PaletteEditor_ContextMenu_Delete_Click(sender, e); + } + protected override Selection CreateSelectionInternal(object content) { throw new NotImplementedException(); @@ -65,10 +139,7 @@ namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Pa return _er; } - public PaletteEditor() - { - InitializeComponent(); - } + private PropertyPanelClass ppclasColor = new PropertyPanelClass("Color", new PropertyPanelProperty[] { new PropertyPanelProperty("Color", typeof(Color)) }); private void PaletteEditor_ContextMenu_Add_Click(object sender, EventArgs e) { @@ -79,8 +150,24 @@ namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Pa if (dlg.ShowDialog() == DialogResult.OK) { BeginEdit(); - palette.Entries.Add(new PaletteEntry(dlg.SelectedColor)); + + PaletteEntry entry = new PaletteEntry(dlg.SelectedColor); + palette.Entries.Add(entry); + cc.Entries.Add(entry); + + PropertyPanelObject ppobj = new PropertyPanelObject(entry.Name, ppclasColor); + ppobj.SetExtraData("content", entry); + ppobj.Properties.Add(new PropertyPanelProperty("Color", typeof(Color), entry.Color)); + PropertiesPanel.Objects.Add(ppobj); + + EndEdit(); + + pnlNoColors.Visible = false; + pnlColorInfo.Visible = true; + cc.Visible = true; + + cc.Refresh(); } } private void PaletteEditor_ContextMenu_Change_Click(object sender, EventArgs e) @@ -108,71 +195,43 @@ namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Pa if (MessageDialog.ShowDialog("Do you wish to delete the selected color?", "Delete Selected Color", MessageDialogButtons.YesNo, MessageDialogIcon.Warning) == DialogResult.Yes) { BeginEdit(); + palette.Entries.Remove(SelectedEntry); + cc.Entries.Remove(SelectedEntry); + EndEdit(); SelectedEntry = null; cc.Refresh(); + + if (palette.Entries.Count == 0) + { + cc.Visible = false; + pnlNoColors.Visible = true; + pnlColorInfo.Visible = false; + } + else + { + cc.Visible = true; + pnlNoColors.Visible = false; + pnlColorInfo.Visible = true; + } } } private int paletteEntryWidth = 64; private int paletteEntryHeight = 24; - private double _ZoomFactor = 1.0; public double ZoomFactor { - get - { - return _ZoomFactor; - } - set - { - _ZoomFactor = value; - cc.Refresh(); - } + get { return cc.ZoomFactor; } + set { cc.ZoomFactor = value; } } - public PaletteEntry HitTest(Vector2D location) + void txtColorName_KeyDown(object sender, KeyEventArgs e) { - PaletteObjectModel palette = (ObjectModel as PaletteObjectModel); - if (palette == null) return null; - - int x = 0, y = 0, w = (int)(paletteEntryWidth * ZoomFactor), h = (int)(paletteEntryHeight * ZoomFactor); - y = (int)cc.VerticalAdjustment.Value; - - - int startIndex = (int)(cc.VerticalAdjustment.Value / h) * GetLineWidth(), endIndex = palette.Entries.Count - 1; - int startLine = startIndex / w; - y = (int)cc.VerticalAdjustment.Value; - - int zcount = 0; - for (int i = startIndex; i <= endIndex; i++) - { - if (x > (int)(cc.Size.Width - w)) - { - x = 0; - y += h; - } - - Rectangle rect = new Rectangle(x + paletteSpacingX, y + paletteSpacingY, w - paletteSpacingX - paletteSpacingX, h - paletteSpacingY - paletteSpacingY); - - if (rect.Contains(location)) - return palette.Entries[i]; - - x += w; - } - return null; - } - public PaletteEntry HitTest(double x, double y) - { - return HitTest(new Vector2D(x, y)); - } - - void txtColorName_KeyDown(object sender, MBS.Framework.UserInterface.Input.Keyboard.KeyEventArgs e) - { - if (e.Key == MBS.Framework.UserInterface.Input.Keyboard.KeyboardKey.Enter) + if (e.Key == KeyboardKey.Enter) { if (SelectedEntry != null) { @@ -183,17 +242,20 @@ namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Pa } } - private void cc_MouseDown(object sender, MBS.Framework.UserInterface.Input.Mouse.MouseEventArgs e) + [EventHandler(nameof(cc), nameof(UserInterface.Controls.ColorPalette.ColorPaletteControl.SelectionChanged))] + private void cc_SelectionChanged(object sender, EventArgs e) { - cc.Focus(); + SelectedEntry = cc.SelectedEntry; - PaletteEntry entry = HitTest(e.Location); - if (entry != null) + Selections.Clear(); + if (cc.SelectedEntry != null) { - SelectedEntry = entry; + Selections.Add(new PaletteEntrySelection(cc.SelectedEntry)); } } + /* + [EventHandler(nameof(cc), nameof(Control.KeyDown))] private void cc_KeyDown(object sender, KeyEventArgs e) { switch (e.Key) @@ -293,21 +355,24 @@ namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Pa } } } + */ - private int GetLineWidth() - { - return (int)((double)cc.Size.Width / (paletteEntryWidth * ZoomFactor)); - } - + [EventHandler(nameof(cc), nameof(Control.MouseDoubleClick))] private void cc_MouseDoubleClick(object sender, MBS.Framework.UserInterface.Input.Mouse.MouseEventArgs e) { - SelectedEntry = HitTest(e.Location); + SelectedEntry = cc.HitTest(e.Location); if (SelectedEntry != null) { DisplayEntryProperties(SelectedEntry); } } + [EventHandler(nameof(cmdAddColor), nameof(Control.Click))] + private void cmdAddColor_Click(object sender, EventArgs e) + { + PaletteEditor_ContextMenu_Add_Click(sender, e); + } + public void DisplayEntryProperties(PaletteEntry entry) { if (entry == null) @@ -352,7 +417,7 @@ namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Pa bool changed = (_SelectedEntry != value); if (!changed) return; - if (SelectedEntry != null) + if (value != null) { ContextMenuCommandID = "PaletteEditor_ContextMenu_Selected"; } @@ -362,108 +427,52 @@ namespace UniversalEditor.Plugins.Multimedia.UserInterface.Editors.Multimedia.Pa } Selections.Clear(); - Selections.Add(new PaletteEntrySelection(value)); + + if (value != null) + { + Selections.Add(new PaletteEntrySelection(value)); + } System.ComponentModel.CancelEventArgs ce = new System.ComponentModel.CancelEventArgs(); OnSelectionChanging(ce); if (ce.Cancel) return; _SelectedEntry = value; + cc.SelectedEntry = _SelectedEntry; OnSelectionChanged(EventArgs.Empty); cc.Refresh(); } } - private TextureBrush AlphaBackgroundBrush = null; - private void DrawAlphaBackground(Graphics g, Rectangle rect) - { - // this is too slow for now, do absolutely nothing - return; - - /* - if (AlphaBackgroundBrush == null) - { - Image AlphaBackgroundImage = Image.Create(24, 24); - Graphics g = Graphics.FromImage(AlphaBackgroundImage); - g.FillRectangle(Brushes.White, new Rectangle(0, 0, 24, 24)); - g.FillRectangle(Brushes.Black, new Rectangle(16, 16, 16, 16)); - - AlphaBackgroundBrush = new TextureBrush(AlphaBackgroundImage); - } - */ - int qs = 0; - for (int patternY = 0; patternY < rect.Height; patternY += 8) - { - for (int patternX = qs; patternX < rect.Width - qs; patternX += 8) - { - g.FillRectangle(Brushes.Black, new Rectangle(rect.X + patternX, rect.Y + patternY, 4, 4)); - } - if (qs == 0) - { - qs = 8; - } - else - { - qs = 0; - } - } - // e.Graphics.FillRectangle(AlphaBackgroundBrush, rect); - } - - int paletteSpacingX = 2; - int paletteSpacingY = 2; - - private void cc_Paint(object sender, PaintEventArgs e) - { - PaletteObjectModel palette = (ObjectModel as PaletteObjectModel); - if (palette == null) return; - - int x = 0, y = 0, w = (int)(paletteEntryWidth * ZoomFactor), h = (int)(paletteEntryHeight * ZoomFactor); - - double shscrh = palette.Entries.Count / GetLineWidth(); - cc.ScrollBounds = new Dimension2D(0, (shscrh * h) + h); - - int startIndex = (int)(cc.VerticalAdjustment.Value / h) * GetLineWidth(), endIndex = palette.Entries.Count - 1; - int startLine = startIndex / w; - y = (int)cc.VerticalAdjustment.Value; - - int zcount = 0; - for (int i = startIndex; i <= endIndex; i++) - { - if (x > (int)(cc.Size.Width - w)) - { - x = 0; - y += h; - } - - if (y > (int)(cc.VerticalAdjustment.Value + cc.Size.Height + h + h)) - { - // we're done for now - return; - } - - Rectangle rect = new Rectangle(x + paletteSpacingX, y + paletteSpacingY, w - paletteSpacingX - paletteSpacingX, h - paletteSpacingY - paletteSpacingY); - - PaletteEntry entry = palette.Entries[i]; - if (entry.Color.A < 1.0) - { - // only fill the alpha background if we need to - DrawAlphaBackground(e.Graphics, rect); - } - e.Graphics.FillRectangle(new SolidBrush(entry.Color), rect); - if (entry == SelectedEntry) - { - e.Graphics.DrawRectangle(new Pen(SystemColors.HighlightBackground, new Measurement(2, MeasurementUnit.Pixel)), new Rectangle(x, y, w, h)); - } - zcount++; - x += w; - } - } protected override void OnObjectModelChanged(EventArgs e) { - base.OnObjectModelChanged(e); - Refresh(); + if (!IsCreated) return; + + cc.Entries.Clear(); + + PaletteObjectModel palette = (ObjectModel as PaletteObjectModel); + if (palette == null) return; + + if (palette.Entries.Count > 0) + { + pnlNoColors.Visible = false; + pnlColorInfo.Visible = true; + cc.Visible = true; + } + else + { + pnlNoColors.Visible = true; + pnlColorInfo.Visible = false; + cc.Visible = false; + } + + foreach (PaletteEntry entry in palette.Entries) + { + cc.Entries.Add(entry); + } + + cc.Refresh(); } diff --git a/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/PaletteEditor.glade b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/PaletteEditor.glade new file mode 100644 index 00000000..3d2f0a43 --- /dev/null +++ b/Plugins.UserInterface/UniversalEditor.Plugins.Multimedia.UserInterface/Editors/Multimedia/Palette/PaletteEditor.glade @@ -0,0 +1,155 @@ + + + + + + False + + + + + + True + False + vertical + + + True + False + + + True + False + Add + Add + True + gtk-add + + + False + True + + + + + True + False + Edit + Edit + True + gtk-edit + + + False + True + + + + + True + False + Remove + Remove + True + gtk-remove + + + False + True + + + + + False + True + 0 + + + + + UniversalEditor.Plugins.Multimedia.UserInterface.Controls.ColorPalette.ColorPaletteControl + True + False + + + True + True + 1 + + + + + False + center + center + vertical + + + True + False + 32 + 32 + 32 + 32 + No colors yet + + + + + + + True + True + 0 + + + + + _Add Color + True + True + True + center + center + True + + + True + True + 1 + + + + + True + True + 2 + + + + + True + False + vertical + + + True + True + + + False + True + 0 + + + + + False + True + 3 + + + + + + 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 0bcafffe..9ad2aa81 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 @@ -36,7 +36,6 @@ - @@ -59,6 +58,8 @@ + + @@ -81,6 +82,7 @@ + @@ -116,6 +118,8 @@ + + \ No newline at end of file diff --git a/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/Adobe/ACOColorPalette.uexml b/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/Adobe/ACOColorPalette.uexml index 445f4a01..9fa7a86f 100644 --- a/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/Adobe/ACOColorPalette.uexml +++ b/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/Adobe/ACOColorPalette.uexml @@ -18,7 +18,7 @@ - + diff --git a/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/Adobe/ACTColorPalette.uexml b/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/Adobe/ACTColorPalette.uexml new file mode 100644 index 00000000..a8c718d1 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/Adobe/ACTColorPalette.uexml @@ -0,0 +1,20 @@ + + + + + + + + *.act + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/Adobe/AdobeSwatchExchange.uexml b/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/Adobe/AdobeSwatchExchange.uexml index fb104985..a5fd7555 100644 --- a/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/Adobe/AdobeSwatchExchange.uexml +++ b/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/Adobe/AdobeSwatchExchange.uexml @@ -18,7 +18,7 @@ - + diff --git a/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/RIFFPalette.uexml b/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/RIFFPalette.uexml new file mode 100644 index 00000000..91eab09d --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.Multimedia/Associations/Palette/RIFFPalette.uexml @@ -0,0 +1,25 @@ + + + + + + + + *.gpl + + + + GIMP Palette + + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugins/UniversalEditor.Plugins.Multimedia/DataFormats/Multimedia/Palette/PaintShop/PaintShopPaletteDataFormat.cs b/Plugins/UniversalEditor.Plugins.Multimedia/DataFormats/Multimedia/Palette/PaintShop/PaintShopPaletteDataFormat.cs index 31cde8d5..1e202847 100644 --- a/Plugins/UniversalEditor.Plugins.Multimedia/DataFormats/Multimedia/Palette/PaintShop/PaintShopPaletteDataFormat.cs +++ b/Plugins/UniversalEditor.Plugins.Multimedia/DataFormats/Multimedia/Palette/PaintShop/PaintShopPaletteDataFormat.cs @@ -70,7 +70,18 @@ namespace UniversalEditor.DataFormats.Multimedia.Palette.PaintShop protected override void SaveInternal(ObjectModel objectModel) { - throw new NotImplementedException(); + PaletteObjectModel palette = (objectModel as PaletteObjectModel); + if (palette == null) throw new ObjectModelNotSupportedException(); + + IO.Writer tw = base.Accessor.Writer; + tw.WriteLine("JASC-PAL"); + + tw.WriteLine(); + tw.WriteLine(palette.Entries.Count.ToString()); + foreach (PaletteEntry entry in palette.Entries) + { + tw.WriteLine(String.Format("{0} {1} {2}", entry.Color.GetRedByte(), entry.Color.GetGreenByte(), entry.Color.GetBlueByte())); + } } } } diff --git a/Plugins/UniversalEditor.Plugins.Multimedia/UniversalEditor.Plugins.Multimedia.csproj b/Plugins/UniversalEditor.Plugins.Multimedia/UniversalEditor.Plugins.Multimedia.csproj index ad6b565d..ba50ee81 100644 --- a/Plugins/UniversalEditor.Plugins.Multimedia/UniversalEditor.Plugins.Multimedia.csproj +++ b/Plugins/UniversalEditor.Plugins.Multimedia/UniversalEditor.Plugins.Multimedia.csproj @@ -78,8 +78,6 @@ - - @@ -341,6 +339,10 @@ + + + + @@ -403,6 +405,9 @@ + + + @@ -474,6 +479,8 @@ + + \ No newline at end of file diff --git a/Plugins/UniversalEditor.Plugins.Office/Associations/Palette/OpenDocumentPalette.uexml b/Plugins/UniversalEditor.Plugins.Office/Associations/Palette/OpenDocumentPalette.uexml new file mode 100644 index 00000000..8ae2dceb --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.Office/Associations/Palette/OpenDocumentPalette.uexml @@ -0,0 +1,20 @@ + + + + + + + + *.soc + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugins/UniversalEditor.Plugins.Office/DataFormats/Multimedia/Palette/OpenDocument/OpenDocumentSOCPaletteDataFormat.cs b/Plugins/UniversalEditor.Plugins.Office/DataFormats/Multimedia/Palette/OpenDocument/OpenDocumentSOCPaletteDataFormat.cs new file mode 100644 index 00000000..a32402f4 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.Office/DataFormats/Multimedia/Palette/OpenDocument/OpenDocumentSOCPaletteDataFormat.cs @@ -0,0 +1,90 @@ +// +// OpenDocumentSOCPaletteDataFormat.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 System.Collections.Generic; +using System.Linq; +using MBS.Framework.Drawing; +using UniversalEditor.DataFormats.Markup.XML; +using UniversalEditor.ObjectModels.Markup; +using UniversalEditor.ObjectModels.Multimedia.Palette; + +namespace UniversalEditor.DataFormats.Multimedia.Palette.OpenDocument +{ + public class OpenDocumentSOCPaletteDataFormat : XMLDataFormat + { + private static DataFormatReference _dfr = null; + protected override DataFormatReference MakeReferenceInternal() + { + if (_dfr == null) + { + _dfr = base.MakeReferenceInternal(); + + _dfr.Capabilities.Clear(); + _dfr.Capabilities.Add(typeof(PaletteObjectModel), DataFormatCapabilities.All); + _dfr.Title = "OpenDocument / OpenOffice / LibreOffice color palette"; + } + return _dfr; + } + + protected override void BeforeLoadInternal(Stack objectModels) + { + base.BeforeLoadInternal(objectModels); + objectModels.Push(new MarkupObjectModel()); + } + protected override void BeforeSaveInternal(Stack objectModels) + { + base.BeforeSaveInternal(objectModels); + } + protected override void AfterLoadInternal(Stack objectModels) + { + base.AfterLoadInternal(objectModels); + + MarkupObjectModel mom = (objectModels.Pop() as MarkupObjectModel); + PaletteObjectModel palette = (objectModels.Pop() as PaletteObjectModel); + if (palette == null) throw new ObjectModelNotSupportedException(); + + MarkupTagElement tagColorTable = mom.FindElementUsingSchema(OpenDocumentXMLSchemas.Office2004, "color-table") as MarkupTagElement; + string drawSchema = OpenDocumentXMLSchemas.DrawUrn; + if (tagColorTable == null) + { + tagColorTable = mom.FindElementUsingSchema(OpenDocumentXMLSchemas.Office2000, "color-table") as MarkupTagElement; + drawSchema = OpenDocumentXMLSchemas.Draw2000; + } + + if (tagColorTable == null) + throw new InvalidDataFormatException("could not find color-table tag in OpenOffice 2000 or 2004 schema"); + + foreach (MarkupTagElement tagColor in tagColorTable.Elements.OfType()) + { + if (!(tagColor.XMLSchema == drawSchema && tagColor.Name == "color")) continue; + + MarkupAttribute attName = tagColor.FindAttributeUsingSchema(drawSchema, "name"); + MarkupAttribute attColor = tagColor.FindAttributeUsingSchema(drawSchema, "color"); + if (attColor == null) continue; + + PaletteEntry entry = new PaletteEntry(); + entry.Name = attName?.Value; + entry.Color = Color.Parse(attColor.Value); + palette.Entries.Add(entry); + } + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.Office/DataFormats/Multimedia/Palette/OpenDocument/OpenDocumentXMLSchemas.cs b/Plugins/UniversalEditor.Plugins.Office/DataFormats/Multimedia/Palette/OpenDocument/OpenDocumentXMLSchemas.cs new file mode 100644 index 00000000..454e5fd1 --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.Office/DataFormats/Multimedia/Palette/OpenDocument/OpenDocumentXMLSchemas.cs @@ -0,0 +1,32 @@ +// +// OpenDocumentXMLSchemas.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; +namespace UniversalEditor.DataFormats.Multimedia.Palette.OpenDocument +{ + public static class OpenDocumentXMLSchemas + { + public static string DrawUrn { get; } = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"; + public static string Draw2000 { get; } = "http://openoffice.org/2000/drawing"; + + public static string Office2000 { get; } = "http://openoffice.org/2000/office"; + public static string Office2004 { get; } = "http://openoffice.org/2004/office"; + } +} diff --git a/Plugins/UniversalEditor.Plugins.Office/UniversalEditor.Plugins.Office.csproj b/Plugins/UniversalEditor.Plugins.Office/UniversalEditor.Plugins.Office.csproj index d27d7b19..d32124a5 100644 --- a/Plugins/UniversalEditor.Plugins.Office/UniversalEditor.Plugins.Office.csproj +++ b/Plugins/UniversalEditor.Plugins.Office/UniversalEditor.Plugins.Office.csproj @@ -48,6 +48,8 @@ + + @@ -62,6 +64,8 @@ + + @@ -84,6 +88,7 @@ + \ No newline at end of file diff --git a/Plugins/UniversalEditor.Plugins.UnrealEngine/DataFormats/Multimedia/Palette/Unreal/UnrealPaletteDataFormat.cs b/Plugins/UniversalEditor.Plugins.UnrealEngine/DataFormats/Multimedia/Palette/Unreal/UnrealPaletteDataFormat.cs new file mode 100644 index 00000000..ef431a7f --- /dev/null +++ b/Plugins/UniversalEditor.Plugins.UnrealEngine/DataFormats/Multimedia/Palette/Unreal/UnrealPaletteDataFormat.cs @@ -0,0 +1,81 @@ +// +// UnrealPaletteDataFormat.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.Drawing; +using UniversalEditor.IO; +using UniversalEditor.ObjectModels.Multimedia.Palette; + +namespace UniversalEditor.DataFormats.Multimedia.Palette.Unreal +{ + public class UnrealPaletteDataFormat : DataFormat + { + public UnrealPaletteDataFormat() + { + } + + protected override void LoadInternal(ref ObjectModel objectModel) + { + PaletteObjectModel palette = (objectModel as PaletteObjectModel); + if (palette == null) throw new ObjectModelNotSupportedException(); + + Reader reader = Accessor.Reader; + ushort signature = reader.ReadUInt16(); + + while (!reader.EndOfStream) + { + byte r = reader.ReadByte(); + byte g = reader.ReadByte(); + byte b = reader.ReadByte(); + byte a = reader.ReadByte(); + palette.Entries.Add(Color.FromRGBAByte(r, g, b, a)); + } + } + + protected override void SaveInternal(ObjectModel objectModel) + { + PaletteObjectModel palette = (objectModel as PaletteObjectModel); + if (palette == null) throw new ObjectModelNotSupportedException(); + + Writer writer = Accessor.Writer; + writer.WriteUInt16(0x4001); + + for (int i = 0; i < Math.Min(palette.Entries.Count, 256); i++) + { + writer.WriteByte(palette.Entries[i].Color.GetRedByte()); + writer.WriteByte(palette.Entries[i].Color.GetGreenByte()); + writer.WriteByte(palette.Entries[i].Color.GetBlueByte()); + writer.WriteByte(palette.Entries[i].Color.GetAlphaByte()); + } + + int remaining = (256 - palette.Entries.Count); + if (remaining > 0) + { + for (int i = 0; i < remaining; i++) + { + writer.WriteByte(0); + writer.WriteByte(0); + writer.WriteByte(0); + writer.WriteByte(0); + } + } + } + } +} diff --git a/Plugins/UniversalEditor.Plugins.UnrealEngine/UniversalEditor.Plugins.UnrealEngine.csproj b/Plugins/UniversalEditor.Plugins.UnrealEngine/UniversalEditor.Plugins.UnrealEngine.csproj index 8e27866a..a921f4d8 100644 --- a/Plugins/UniversalEditor.Plugins.UnrealEngine/UniversalEditor.Plugins.UnrealEngine.csproj +++ b/Plugins/UniversalEditor.Plugins.UnrealEngine/UniversalEditor.Plugins.UnrealEngine.csproj @@ -52,6 +52,7 @@ + @@ -62,13 +63,26 @@ {30467E5C-05BC-4856-AADC-13906EF4CADD} UniversalEditor.Essential + + {BE4D0BA3-0888-42A5-9C09-FC308A4509D2} + UniversalEditor.Plugins.Multimedia + + + {00266B21-35C9-4A7F-A6BA-D54D7FDCC25C} + MBS.Framework + + + + + +