Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

String-related fixes and improvements. #977

Merged
merged 6 commits into from
Jun 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions UndertaleModLib/UndertaleData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ public object this[Type resourceType]
{
get
{
if (!typeof(UndertaleNamedResource).IsAssignableFrom(resourceType))
throw new NotSupportedException($"\"{resourceType.FullName}\" is not a UndertaleNamedResource.");
if (!typeof(UndertaleResource).IsAssignableFrom(resourceType))
throw new NotSupportedException($"\"{resourceType.FullName}\" is not an UndertaleResource.");

var property = GetType().GetProperties().Where(x => x.PropertyType.Name == "IList`1")
.FirstOrDefault(x => x.PropertyType.GetGenericArguments()[0] == resourceType);
Expand All @@ -67,8 +67,8 @@ public object this[Type resourceType]
}
set
{
if (!typeof(UndertaleNamedResource).IsAssignableFrom(resourceType))
throw new NotSupportedException($"\"{resourceType.FullName}\" is not a UndertaleNamedResource.");
if (!typeof(UndertaleResource).IsAssignableFrom(resourceType))
throw new NotSupportedException($"\"{resourceType.FullName}\" is not an UndertaleResource.");

var property = GetType().GetProperties().Where(x => x.PropertyType.Name == "IList`1")
.FirstOrDefault(x => x.PropertyType.GetGenericArguments()[0] == resourceType);
Expand Down
4 changes: 4 additions & 0 deletions UndertaleModTool/Converters/StringTitleConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ namespace UndertaleModTool
public class StringTitleConverter : IValueConverter
{
public static readonly Regex NewLineRegex = new(@"\r\n?|\n", RegexOptions.Compiled);
public static StringTitleConverter Instance { get; } = new();

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is not string str)
return null;

if (str.Length == 0)
return "(empty string)";

if (str.Length > 256)
str = str[..256] + "...";
str = NewLineRegex.Replace(str, " ");
Expand Down
11 changes: 2 additions & 9 deletions UndertaleModTool/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -426,15 +426,8 @@
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:Tab}">
<StackPanel Orientation="Horizontal">
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource TabTitleConverter}" Mode="OneWay">
<Binding Mode="OneTime"/>
<Binding Path="OpenedObject" Mode="OneWay"/>
<!-- for notification only -->
<Binding Path="OpenedObject.Name.Content" Mode="OneWay"/>
</MultiBinding>
</TextBlock.Text>
<TextBlock Initialized="TabTitleText_Initialized" DataContextChanged="TabTitleText_DataContextChanged">
<!-- "TextBlock.Text" binding is set in code-behind -->
</TextBlock>
<Button Background="Transparent" Width="16" Height="16" BorderThickness="0" Margin="12,0,0,0"
Click="TabCloseButton_OnClick" MouseEnter="TabCloseButton_MouseEnter" MouseLeave="TabCloseButton_MouseLeave">
Expand Down
120 changes: 98 additions & 22 deletions UndertaleModTool/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,17 @@ public static string GetTitleForObject(object obj)
else if (obj is UndertaleString str)
{
string stringFirstLine = str.Content;
int stringLength = StringTitleConverter.NewLineRegex.Match(stringFirstLine).Index;
if (stringLength != -1)
stringFirstLine = stringFirstLine[..stringLength] + " ...";
if (stringFirstLine is not null)
{
if (stringFirstLine.Length == 0)
stringFirstLine = "(empty string)";
else
{
int stringLength = StringTitleConverter.NewLineRegex.Match(stringFirstLine).Index;
if (stringLength != 0)
stringFirstLine = stringFirstLine[..stringLength] + " ...";
}
}

title = "String - " + stringFirstLine;
}
Expand All @@ -167,8 +175,16 @@ public static string GetTitleForObject(object obj)
Debug.WriteLine($"Could not handle type {obj.GetType()}");
}

if (title.Length > 64)
title = title[..64] + "...";
if (title is not null)
{
// "\t" is displayed as 8 spaces.
// So, replace all "\t" with spaces,
// in order to properly shorten the title.
title = title.Replace("\t", " ");

if (title.Length > 64)
title = title[..64] + "...";
}

return title;
}
Expand All @@ -181,13 +197,15 @@ public override string ToString()
}
public class TabTitleConverter : IMultiValueConverter
{
public static TabTitleConverter Instance { get; } = new();

public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values[0] is not Tab tab)
return null;

if (!tab.IsCustomTitle)
tab.TabTitle = Tab.GetTitleForObject(values[1]);
tab.TabTitle = Tab.GetTitleForObject(tab.OpenedObject);

return tab.TabTitle;
}
Expand Down Expand Up @@ -1710,10 +1728,17 @@ private void DeleteItem(UndertaleObject obj)
}
}
}
private void CopyItemName(UndertaleNamedResource namedRes)
private void CopyItemName(object obj)
{
if (namedRes.Name?.Content is not null)
Clipboard.SetText(namedRes.Name.Content);
string name = null;

if (obj is UndertaleNamedResource namedRes)
name = namedRes.Name?.Content;
else if (obj is UndertaleString str && str.Content?.Length > 0)
name = StringTitleConverter.Instance.Convert(str.Content, null, null, null) as string;

if (name is not null)
Clipboard.SetText(name);
else
this.ShowWarning("Item name is null.");
}
Expand Down Expand Up @@ -1798,8 +1823,7 @@ private void MenuItem_OpenInNewTab_Click(object sender, RoutedEventArgs e)
}
private void MenuItem_CopyName_Click(object sender, RoutedEventArgs e)
{
if (Highlighted is UndertaleNamedResource namedRes)
CopyItemName(namedRes);
CopyItemName(Highlighted);
}
private void MenuItem_Delete_Click(object sender, RoutedEventArgs e)
{
Expand Down Expand Up @@ -1894,6 +1918,8 @@ private void MenuItem_Add_Click(object sender, RoutedEventArgs e)
(obj as UndertaleNamedResource).Name = new UndertaleString(notDataNewName); // not Data.MakeString!
}
}
else if (obj is UndertaleString str)
str.Content = "string" + list.Count;
list.Add(obj);
UpdateTree();
HighlightObject(obj);
Expand Down Expand Up @@ -3033,8 +3059,11 @@ public void HighlightObject(object obj, bool silent = true)
UndertaleResource res = obj as UndertaleResource;
if (res is null)
{
if (!silent)
this.ShowWarning($"Can't highlight the object - it's null or isn't a UndertaleResource.");
string msg = $"Can't highlight the object - it's null or isn't an UndertaleResource.";
if (silent)
Debug.WriteLine(msg);
else
this.ShowWarning(msg);

return;
}
Expand All @@ -3060,16 +3089,22 @@ public void HighlightObject(object obj, bool silent = true)
}
catch (Exception ex)
{
if (!silent)
this.ShowWarning($"Can't highlight the object \"{objName}\".\nError - {ex.Message}");
string msg = $"Can't highlight the object \"{objName}\".\nError - {ex.Message}";
if (silent)
Debug.WriteLine(msg);
else
this.ShowWarning(msg);

return;
}

if (resListView is null)
{
if (!silent)
this.ShowWarning($"Can't highlight the object \"{objName}\" - element with object list not found.");
string msg = $"Can't highlight the object \"{objName}\" - element with object list not found.";
if (silent)
Debug.WriteLine(msg);
else
this.ShowWarning(msg);

return;
}
Expand Down Expand Up @@ -3568,6 +3603,52 @@ private void CloseOtherTabsMenuItem_Click(object sender, RoutedEventArgs e)
Tabs = new() { tab };
CurrentTabIndex = 0;
}

private void TabTitleText_Initialized(object sender, EventArgs e)
{
SetTabTitleBinding(sender, null);
}
private void TabTitleText_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
SetTabTitleBinding(sender, e.OldValue);
}
private void SetTabTitleBinding(object sender, object prevObj)
{
TextBlock textBlock = sender as TextBlock;
object obj = (textBlock.DataContext as Tab)?.OpenedObject;
if (obj is null || obj == DependencyProperty.UnsetValue)
return;

bool objNamed = obj is UndertaleNamedResource;
bool objString = obj is UndertaleString;

prevObj = (prevObj as Tab)?.OpenedObject;
if (prevObj is not null)
{
bool pObjNamed = prevObj is UndertaleNamedResource;
bool pObjString = prevObj is UndertaleString;

// if both objects have the same type (one of above)
// or both objects are not "UndertaleNamedResource",
// then there's no need for changing the binding
if (pObjNamed && objNamed || pObjString && objString || !(pObjNamed || objNamed))
return;
}

MultiBinding binding = new()
{
Converter = TabTitleConverter.Instance,
Mode = BindingMode.OneWay
};
binding.Bindings.Add(new Binding() { Mode = BindingMode.OneTime });

if (objNamed)
binding.Bindings.Add(new Binding("OpenedObject.Name.Content") { Mode = BindingMode.OneWay });
else if (objString)
binding.Bindings.Add(new Binding("OpenedObject.Content") { Mode = BindingMode.OneWay });

textBlock.SetBinding(TextBlock.TextProperty, binding);
}
}

public class GeneralInfoEditor
Expand Down Expand Up @@ -3609,11 +3690,6 @@ public class DescriptionView
public string Heading { get; private set; }
public string Description { get; private set; }

// Used only by the "TabTitleConverter" to prevent the following WPF binding warning:
// "Name property not found on object of type DescriptionView".
// (within "TabControl.ItemTemplate")
public UndertaleString Name { get; } = new();

public DescriptionView(string heading, string description)
{
Heading = heading;
Expand Down