// // /*=============================================================================== // // Copyright (C) 2025 PhantomsXR Ltd. All Rights Reserved. // // // // This file is part of the Phantom.XRMOD.XRMODLocalization.Editor. // // // // The XR-MOD cannot be copied, distributed, or made available to // // third-parties for commercial purposes without written permission of PhantomsXR Ltd. // // // // Contact nswell@phantomsxr.com for licensing requests. // // ===============================================================================*/ using System; using System.Collections.Generic; using System.Runtime.InteropServices; using Phantom.XRMOD.Localization.Runtime; using UnityEditor; using UnityEditor.VersionControl; using UnityEngine; using UnityEngine.UIElements; namespace Phantom.XRMOD.Localization.Editor { public class RightEditorPanel : IEditorDraw { private MultiColumnListView tableMCLV; private VisualElement rightPane; private LocalizationEditorWindow editorWindow; private LocalizationTable table; private int currentSelectedIndex = -1; private const int _CONST_COLUMN_WIDTH = 130; private const int _CONST_COLUMN_HEIGHT = 30; private VisualElement hintLabel; public RightEditorPanel(VisualElement _rightPane, LocalizationEditorWindow _editorWindow) { this.rightPane = _rightPane; editorWindow = _editorWindow; } public void Draw() { table = SharedData.Instance.Table; OnCreateUI(); } private void OnCreateUI() { tableMCLV = new MultiColumnListView { name = "Right Pane Table", style = { flexGrow = 1, display = DisplayStyle.None, }, reorderable = false, selectionType = SelectionType.Single, showAlternatingRowBackgrounds = AlternatingRowBackground.All, fixedItemHeight = _CONST_COLUMN_HEIGHT + 5, columns = { resizable = true, stretchMode = Columns.StretchMode.Grow } }; tableMCLV.columns.Clear(); tableMCLV.AddManipulator(new ContextualMenuManipulator(_evt => { _evt.menu.AppendAction("Add Column", AddColumnAction); _evt.menu.AppendAction(GetColumnSyncState() ? "Sync" : "UnSync", (_data) => { Utilities.SetKeyEntryLockState(currentSelectedIndex, !table.Entries[currentSelectedIndex].Sync); editorWindow.RefreshEntryList(); }, currentSelectedIndex == -1 ? DropdownMenuAction.Status.Disabled : DropdownMenuAction.Status.Normal); _evt.menu.AppendSeparator(); _evt.menu.AppendAction("Remove Column", (_data) => { Utilities.RemoveKeyEntry(currentSelectedIndex); editorWindow.RefreshTableList(); }, currentSelectedIndex == -1 ? DropdownMenuAction.Status.Disabled : DropdownMenuAction.Status.Normal); })); tableMCLV.selectedIndicesChanged += TableMCLVOnselectionChanged; rightPane.Add(tableMCLV); hintLabel = new VisualElement() { style = {display = DisplayStyle.None} }; hintLabel.AddToClassList("select-table"); var tmp_HintLabel = new Label() { text = "Select a table please", }; hintLabel.Add(tmp_HintLabel); rightPane.Add(hintLabel); if (table != null) { BuildColumns(); hintLabel.style.display = DisplayStyle.None; tableMCLV.style.display = DisplayStyle.Flex; } else { hintLabel.style.display = DisplayStyle.Flex; tableMCLV.style.display = DisplayStyle.None; } } private void TableMCLVOnselectionChanged(IEnumerable _obj) { foreach (int tmp_I in _obj) { currentSelectedIndex = tmp_I; } } private void BuildColumns() { if (table == null) return; tableMCLV.columns.Clear(); tableMCLV.columns.Add(new Column() { title = "", resizable = false, width = 16, makeCell = () => { var tmp_Image = new Image { name = "MenuIcon", image = Utilities.MenuIconTexture, scaleMode = ScaleMode.ScaleToFit, style = { width = 16, height = 16, alignSelf = Align.Center, marginLeft = StyleKeyword.Auto, marginRight = StyleKeyword.Auto, } }; var tmp_Container = new VisualElement { pickingMode = PickingMode.Ignore, style = { flexGrow = 1, flexDirection = FlexDirection.Row, justifyContent = Justify.Center, alignItems = Align.Center, } }; tmp_Container.Add(tmp_Image); return tmp_Container; }, bindCell = (_element, _i) => { if (table == null || table.Entries.Count == 0) return; _element.Q("MenuIcon").image = table.Entries[_i].Sync ? Utilities.UnSyncIconTexture : Utilities.SyncIconTexture; } }); tableMCLV.RegisterCallback(_evt => { if (_evt.target is not VisualElement tmp_Element) return; if (Utilities.IsClickBlank(tmp_Element)) { currentSelectedIndex = -1; tableMCLV.ClearSelection(); } }); tableMCLV.RegisterCallback(_evt => { if (_evt.target is not VisualElement tmp_Element) return; if (Utilities.IsClickBlank(tmp_Element)) { currentSelectedIndex = -1; tableMCLV.ClearSelection(); } }); tableMCLV.columns.Add(new Column() { title = "Key", width = _CONST_COLUMN_WIDTH, resizable = false, makeCell = MakeKeyHeaderCell(), bindCell = BindKeyHeaderCell() }); HashSet tmp_LanguageSet = new HashSet(); foreach (var tmp_Entry in table.Entries) { foreach (var tmp_Pair in tmp_Entry.Translations) { tmp_LanguageSet.Add(tmp_Pair.Language.ToString()); } } foreach (var tmp_LangStr in tmp_LanguageSet) { var tmp_LanguageStr = tmp_LangStr; var tmp_Column = new Column() { name = tmp_LanguageStr, title = tmp_LanguageStr, width = _CONST_COLUMN_WIDTH, makeCell = MakeLanguageKeyCell(tmp_LanguageStr), bindCell = BindLanguageKeyCell(tmp_LanguageStr) }; tableMCLV.columns.Add(tmp_Column); } } private void AddColumnAction(DropdownMenuAction _obj) { Utilities.AddNewKeyEntry(); EditorUtility.SetDirty(SharedData.Instance.Table); editorWindow.RefreshEntryList(); } private static Func MakeLanguageKeyCell(string _languageStr) { return () => new TextField() { name = _languageStr, style = { height = _CONST_COLUMN_HEIGHT, }, }; } private Action BindLanguageKeyCell(string _languageStr) { return (_ve, _i) => { if (table == null || table.Entries.Count == 0) return; var tmp_Tf = _ve as TextField; var tmp_Entry = table.Entries[_i]; var tmp_Translation = tmp_Entry.Translations.Find(t => t.Language.ToString() == _languageStr); if (tmp_Tf == null) return; tmp_Tf.value = tmp_Translation != null ? tmp_Translation.Text : ""; tmp_Tf.RegisterValueChangedCallback(_evt => { if (tmp_Translation == null) return; tmp_Translation.Text = _evt.newValue; EditorUtility.SetDirty(table); }); }; } private Func MakeKeyHeaderCell() { return () => { var tmp_TextField = new TextField() { name = $"Key-{tableMCLV.columns.Count - 1}", style = { height = _CONST_COLUMN_HEIGHT, } }; return tmp_TextField; }; } private Action BindKeyHeaderCell() { return (_ve, _i) => { if (table == null || table.Entries.Count == 0) return; var tmp_Tf = _ve as TextField; if (tmp_Tf == null) return; tmp_Tf.value = table.Entries[_i].Key; tmp_Tf.RegisterValueChangedCallback(_evt => { foreach (var tmp_Table in SharedData.Instance.Database.Tables) { if (tmp_Table.Entries.Count == 0) break; tmp_Table.Entries[_i].Key = tmp_Tf.value; } }); }; } private bool GetColumnSyncState() { if (currentSelectedIndex == -1) return true; return table.Entries[currentSelectedIndex].Sync; } public void ReBuild() { table = SharedData.Instance.Table; BuildColumns(); if (!table) { tableMCLV.columns.Clear(); tableMCLV.Clear(); hintLabel.style.display = DisplayStyle.Flex; tableMCLV.style.display = DisplayStyle.None; return; } tableMCLV!.itemsSource = table.Entries; hintLabel.style.display = DisplayStyle.None; tableMCLV.style.display = DisplayStyle.Flex; tableMCLV!.Rebuild(); } } }