Skip to content

Commit 7bbead4

Browse files
Yu Leng (from Dev Box)claude
andcommitted
[KBM] Reuse Text action for Expand trigger instead of separate ReplaceWith case
When Text Expand trigger is selected, select the existing "Insert text" ComboBoxItem, override its label/icon to "Replace with", and disable the ComboBox. This avoids dynamic ComboBox item replacement that broke the SwitchPresenter binding. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 48e5669 commit 7bbead4

File tree

2 files changed

+43
-87
lines changed

2 files changed

+43
-87
lines changed

src/modules/keyboardmanager/KeyboardManagerEditorUI/Controls/UnifiedMappingControl.xaml

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,10 @@
230230
<TextBlock x:Uid="ActionType_KeyOrShortcut_Text" />
231231
</StackPanel>
232232
</ComboBoxItem>
233-
<ComboBoxItem x:Uid="ActionType_Text" Tag="Text">
233+
<ComboBoxItem x:Name="ActionTypeTextItem" x:Uid="ActionType_Text" Tag="Text">
234234
<StackPanel Orientation="Horizontal" Spacing="8">
235-
<FontIcon FontSize="14" Glyph="&#xE8D2;" />
236-
<TextBlock x:Uid="ActionType_Text_Text" />
235+
<FontIcon x:Name="ActionTypeTextIcon" FontSize="14" Glyph="&#xE8D2;" />
236+
<TextBlock x:Name="ActionTypeTextLabel" x:Uid="ActionType_Text_Text" />
237237
</StackPanel>
238238
</ComboBoxItem>
239239
<ComboBoxItem x:Uid="ActionType_OpenUrl" Tag="OpenUrl">
@@ -409,20 +409,7 @@
409409
</ComboBox>
410410
</StackPanel>
411411
</tkcontrols:Case>
412-
<!-- Replace With Action (for Expand trigger) -->
413-
<tkcontrols:Case Value="ReplaceWith">
414-
<TextBox
415-
x:Name="ExpandedTextBox"
416-
x:Uid="ExpandedTextBox"
417-
MinHeight="120"
418-
MaxHeight="240"
419-
AcceptsReturn="True"
420-
Background="{ThemeResource TextControlBackgroundFocused}"
421-
BorderBrush="{ThemeResource ControlStrokeColorDefaultBrush}"
422-
GotFocus="ExpandedTextBox_GotFocus"
423-
TextChanged="ExpandedTextBox_TextChanged"
424-
TextWrapping="Wrap" />
425-
</tkcontrols:Case>
412+
<!-- Replace With uses the Text case above with label override -->
426413
<!-- Mouse Click Action (Placeholder) -->
427414
<tkcontrols:Case Value="MouseClick">
428415
<TextBlock

src/modules/keyboardmanager/KeyboardManagerEditorUI/Controls/UnifiedMappingControl.xaml.cs

Lines changed: 39 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ public sealed partial class UnifiedMappingControl : UserControl, IDisposable, IK
4444
private bool _urlPathDirty;
4545
private bool _programPathDirty;
4646
private bool _expandAbbreviationDirty;
47-
private bool _expandedTextDirty;
4847

4948
// Expand trigger key tracking
5049
private string _expandTriggerKey = "Space";
5150
private bool _isCapturingExpandTriggerKey;
5251

53-
// Saved action type items for restoring when switching away from Expand trigger
54-
private List<object>? _savedActionTypeItems;
52+
// Saved label/icon for restoring "Text" action item after Expand mode
53+
private string? _savedTextLabel;
54+
private string? _savedTextIconGlyph;
5555

5656
public bool AllowChords { get; set; } = true;
5757

@@ -134,6 +134,12 @@ public ActionType CurrentActionType
134134
{
135135
get
136136
{
137+
// When in Expand trigger mode, the action is always ReplaceWith
138+
if (CurrentTriggerType == TriggerType.Expand)
139+
{
140+
return ActionType.ReplaceWith;
141+
}
142+
137143
if (ActionTypeComboBox?.SelectedItem is ComboBoxItem item)
138144
{
139145
return item.Tag?.ToString() switch
@@ -142,7 +148,6 @@ public ActionType CurrentActionType
142148
"OpenUrl" => ActionType.OpenUrl,
143149
"OpenApp" => ActionType.OpenApp,
144150
"MouseClick" => ActionType.MouseClick,
145-
"ReplaceWith" => ActionType.ReplaceWith,
146151
_ => ActionType.KeyOrShortcut,
147152
};
148153
}
@@ -611,7 +616,7 @@ public bool IsInputComplete()
611616
if (CurrentTriggerType == TriggerType.Expand)
612617
{
613618
return !string.IsNullOrWhiteSpace(ExpandAbbreviationBox?.Text)
614-
&& !string.IsNullOrWhiteSpace(ExpandedTextBox?.Text);
619+
&& !string.IsNullOrWhiteSpace(TextContentBox?.Text);
615620
}
616621

617622
// Trigger keys are always required for other trigger types
@@ -872,7 +877,7 @@ private void UpdateInlineValidation()
872877
return;
873878
}
874879

875-
if (ExpandedTextBox != null && _expandedTextDirty && string.IsNullOrWhiteSpace(ExpandedTextBox.Text))
880+
if (TextContentBox != null && _textContentDirty && string.IsNullOrWhiteSpace(TextContentBox.Text))
876881
{
877882
ShowValidationErrorFromType(ValidationErrorType.EmptyExpandedText);
878883
return;
@@ -901,7 +906,6 @@ public void Reset()
901906
_urlPathDirty = false;
902907
_programPathDirty = false;
903908
_expandAbbreviationDirty = false;
904-
_expandedTextDirty = false;
905909

906910
// Reset expand state
907911
_expandTriggerKey = "Space";
@@ -912,10 +916,7 @@ public void Reset()
912916
ExpandAbbreviationBox.Text = string.Empty;
913917
}
914918

915-
if (ExpandedTextBox != null)
916-
{
917-
ExpandedTextBox.Text = string.Empty;
918-
}
919+
// TextContentBox is shared with expand mode; cleared below with other action fields
919920

920921
if (ExpandTriggerKeyVisual != null)
921922
{
@@ -1139,18 +1140,6 @@ private void ExpandTriggerKeyToggleBtn_Unchecked(object sender, RoutedEventArgs
11391140
}
11401141
}
11411142

1142-
private void ExpandedTextBox_GotFocus(object sender, RoutedEventArgs e)
1143-
{
1144-
CleanupKeyboardHook();
1145-
UncheckAllToggleButtons();
1146-
}
1147-
1148-
private void ExpandedTextBox_TextChanged(object sender, TextChangedEventArgs e)
1149-
{
1150-
_expandedTextDirty = true;
1151-
RaiseValidationStateChanged();
1152-
}
1153-
11541143
private void HideAppSpecific()
11551144
{
11561145
if (AppSpecificCheckBox != null)
@@ -1174,71 +1163,51 @@ private void ShowAppSpecific()
11741163

11751164
private void SwitchActionTypeToReplaceWith()
11761165
{
1177-
if (ActionTypeComboBox == null)
1166+
if (ActionTypeComboBox == null || ActionTypeTextItem == null)
11781167
{
11791168
return;
11801169
}
11811170

1182-
// Save current items if not already saved
1183-
if (_savedActionTypeItems == null)
1184-
{
1185-
_savedActionTypeItems = new List<object>();
1186-
foreach (var actionItem in ActionTypeComboBox.Items)
1187-
{
1188-
_savedActionTypeItems.Add(actionItem);
1189-
}
1190-
}
1191-
1192-
// Replace with single "Replace with" item
1193-
ActionTypeComboBox.Items.Clear();
1171+
// Select the "Text" action item and override its label to "Replace with"
1172+
ActionTypeComboBox.SelectedItem = ActionTypeTextItem;
1173+
ActionTypeComboBox.IsEnabled = false;
11941174

11951175
var resourceLoader = new ResourceLoader();
1196-
var replaceWithItem = new ComboBoxItem
1176+
if (ActionTypeTextLabel != null)
11971177
{
1198-
Tag = "ReplaceWith",
1199-
Content = new StackPanel
1200-
{
1201-
Orientation = Microsoft.UI.Xaml.Controls.Orientation.Horizontal,
1202-
Spacing = 8,
1203-
Children =
1204-
{
1205-
new FontIcon { Glyph = "\uE8C8", FontSize = 14 },
1206-
new TextBlock { Text = resourceLoader.GetString("ActionType_ReplaceWith_Text/Text") },
1207-
},
1208-
},
1209-
};
1210-
1211-
ActionTypeComboBox.Items.Add(replaceWithItem);
1212-
ActionTypeComboBox.SelectedIndex = 0;
1213-
ActionTypeComboBox.IsEnabled = false;
1178+
_savedTextLabel = ActionTypeTextLabel.Text;
1179+
ActionTypeTextLabel.Text = resourceLoader.GetString("ActionType_ReplaceWith_Text/Text");
1180+
}
12141181

1215-
// Manually update SwitchPresenter since programmatic ComboBox item changes
1216-
// may not reliably trigger the SelectedItem.Tag binding update in WinUI.
1217-
ActionSwitchPresenter.Value = "ReplaceWith";
1182+
if (ActionTypeTextIcon != null)
1183+
{
1184+
_savedTextIconGlyph = ActionTypeTextIcon.Glyph;
1185+
ActionTypeTextIcon.Glyph = "\uE8C8";
1186+
}
12181187
}
12191188

12201189
private void RestoreNormalActionTypes()
12211190
{
1222-
if (ActionTypeComboBox == null || _savedActionTypeItems == null)
1191+
if (ActionTypeComboBox == null)
12231192
{
12241193
return;
12251194
}
12261195

1227-
ActionTypeComboBox.Items.Clear();
1228-
foreach (var actionItem in _savedActionTypeItems)
1196+
// Restore original label and icon on the "Text" action item
1197+
if (ActionTypeTextLabel != null && _savedTextLabel != null)
12291198
{
1230-
ActionTypeComboBox.Items.Add(actionItem);
1199+
ActionTypeTextLabel.Text = _savedTextLabel;
1200+
_savedTextLabel = null;
12311201
}
12321202

1233-
_savedActionTypeItems = null;
1234-
ActionTypeComboBox.SelectedIndex = 0;
1235-
ActionTypeComboBox.IsEnabled = true;
1236-
1237-
// Manually sync SwitchPresenter with the restored first item's Tag.
1238-
if (ActionTypeComboBox.SelectedItem is ComboBoxItem selectedItem && selectedItem.Tag is string tag)
1203+
if (ActionTypeTextIcon != null && _savedTextIconGlyph != null)
12391204
{
1240-
ActionSwitchPresenter.Value = tag;
1205+
ActionTypeTextIcon.Glyph = _savedTextIconGlyph;
1206+
_savedTextIconGlyph = null;
12411207
}
1208+
1209+
ActionTypeComboBox.SelectedIndex = 0;
1210+
ActionTypeComboBox.IsEnabled = true;
12421211
}
12431212

12441213
#endregion
@@ -1249,7 +1218,7 @@ private void RestoreNormalActionTypes()
12491218

12501219
public string GetExpandTriggerKey() => _expandTriggerKey;
12511220

1252-
public string GetExpandedText() => ExpandedTextBox?.Text ?? string.Empty;
1221+
public string GetExpandedText() => TextContentBox?.Text ?? string.Empty;
12531222

12541223
#endregion
12551224

@@ -1274,9 +1243,9 @@ public void SetExpandTriggerKey(string triggerKey)
12741243

12751244
public void SetExpandedText(string text)
12761245
{
1277-
if (ExpandedTextBox != null)
1246+
if (TextContentBox != null)
12781247
{
1279-
ExpandedTextBox.Text = text;
1248+
TextContentBox.Text = text;
12801249
}
12811250
}
12821251

0 commit comments

Comments
 (0)