|
13 | 13 | using System; |
14 | 14 | using System.Collections.Generic; |
15 | 15 | using System.Linq; |
| 16 | +using System.Runtime.InteropServices; |
| 17 | +using System.Threading.Tasks; |
16 | 18 | using Windows.System; |
17 | 19 | using Windows.UI.Core; |
18 | 20 |
|
19 | 21 | namespace Files.App |
20 | 22 | { |
21 | 23 | public abstract class StandardViewBase : BaseLayout |
22 | 24 | { |
| 25 | + private const int KEY_DOWN_MASK = 0x8000; |
| 26 | + |
| 27 | + protected int NextRenameIndex = 0; |
| 28 | + |
23 | 29 | protected abstract ListViewBase ListViewBase |
24 | 30 | { |
25 | 31 | get; |
@@ -130,6 +136,7 @@ protected virtual void ZoomIn(object? sender, GroupOption option) |
130 | 136 | protected virtual async void FileList_SelectionChanged(object sender, SelectionChangedEventArgs e) |
131 | 137 | { |
132 | 138 | SelectedItems = ListViewBase.SelectedItems.Cast<ListedItem>().Where(x => x is not null).ToList(); |
| 139 | + |
133 | 140 | if (SelectedItems.Count == 1 && App.AppModel.IsQuickLookAvailable) |
134 | 141 | await QuickLookHelpers.ToggleQuickLook(ParentShellPageInstance, true); |
135 | 142 | } |
@@ -167,48 +174,113 @@ protected virtual void StartRenameItem(string itemNameTextBox) |
167 | 174 | textBox.KeyDown += RenameTextBox_KeyDown; |
168 | 175 |
|
169 | 176 | int selectedTextLength = SelectedItem.Name.Length; |
| 177 | + |
170 | 178 | if (!SelectedItem.IsShortcut && UserSettingsService.FoldersSettingsService.ShowFileExtensions) |
171 | 179 | selectedTextLength -= extensionLength; |
| 180 | + |
172 | 181 | textBox.Select(0, selectedTextLength); |
173 | 182 | IsRenamingItem = true; |
174 | 183 | } |
175 | 184 |
|
176 | 185 | protected abstract void EndRename(TextBox textBox); |
177 | 186 |
|
178 | | - protected virtual async void CommitRename(TextBox textBox) |
| 187 | + protected virtual async Task CommitRename(TextBox textBox) |
179 | 188 | { |
180 | 189 | EndRename(textBox); |
181 | 190 | string newItemName = textBox.Text.Trim().TrimEnd('.'); |
182 | 191 | await UIFilesystemHelpers.RenameFileItemAsync(RenamingItem, newItemName, ParentShellPageInstance); |
183 | 192 | } |
184 | 193 |
|
185 | | - protected virtual void RenameTextBox_LostFocus(object sender, RoutedEventArgs e) |
| 194 | + protected virtual async void RenameTextBox_LostFocus(object sender, RoutedEventArgs e) |
186 | 195 | { |
187 | 196 | // This check allows the user to use the text box context menu without ending the rename |
188 | 197 | if (!(FocusManager.GetFocusedElement(XamlRoot) is AppBarButton or Popup)) |
189 | 198 | { |
190 | 199 | TextBox textBox = (TextBox)e.OriginalSource; |
191 | | - CommitRename(textBox); |
| 200 | + await CommitRename(textBox); |
192 | 201 | } |
193 | 202 | } |
194 | 203 |
|
195 | | - protected void RenameTextBox_KeyDown(object sender, KeyRoutedEventArgs e) |
| 204 | + protected async void RenameTextBox_KeyDown(object sender, KeyRoutedEventArgs e) |
196 | 205 | { |
197 | | - if (e.Key == VirtualKey.Escape) |
| 206 | + var textBox = (TextBox)sender; |
| 207 | + switch (e.Key) |
198 | 208 | { |
199 | | - TextBox textBox = (TextBox)sender; |
200 | | - textBox.LostFocus -= RenameTextBox_LostFocus; |
201 | | - textBox.Text = OldItemName; |
202 | | - EndRename(textBox); |
203 | | - e.Handled = true; |
| 209 | + case VirtualKey.Escape: |
| 210 | + textBox.LostFocus -= RenameTextBox_LostFocus; |
| 211 | + textBox.Text = OldItemName; |
| 212 | + EndRename(textBox); |
| 213 | + e.Handled = true; |
| 214 | + break; |
| 215 | + case VirtualKey.Enter: |
| 216 | + textBox.LostFocus -= RenameTextBox_LostFocus; |
| 217 | + await CommitRename(textBox); |
| 218 | + e.Handled = true; |
| 219 | + break; |
| 220 | + case VirtualKey.Up: |
| 221 | + textBox.SelectionStart = 0; |
| 222 | + e.Handled = true; |
| 223 | + break; |
| 224 | + case VirtualKey.Down: |
| 225 | + textBox.SelectionStart = textBox.Text.Length; |
| 226 | + e.Handled = true; |
| 227 | + break; |
| 228 | + case VirtualKey.Left: |
| 229 | + e.Handled = textBox.SelectionStart == 0; |
| 230 | + break; |
| 231 | + case VirtualKey.Right: |
| 232 | + e.Handled = (textBox.SelectionStart + textBox.SelectionLength) == textBox.Text.Length; |
| 233 | + break; |
| 234 | + case VirtualKey.Tab: |
| 235 | + textBox.LostFocus -= RenameTextBox_LostFocus; |
| 236 | + |
| 237 | + var isShiftPressed = (GetKeyState((int)VirtualKey.Shift) & KEY_DOWN_MASK) != 0; |
| 238 | + NextRenameIndex = isShiftPressed ? -1 : 1; |
| 239 | + |
| 240 | + if (textBox.Text != OldItemName) |
| 241 | + { |
| 242 | + await CommitRename(textBox); |
| 243 | + } |
| 244 | + else |
| 245 | + { |
| 246 | + var newIndex = ListViewBase.SelectedIndex + NextRenameIndex; |
| 247 | + NextRenameIndex = 0; |
| 248 | + EndRename(textBox); |
| 249 | + |
| 250 | + if |
| 251 | + ( |
| 252 | + newIndex >= 0 && |
| 253 | + newIndex < ListViewBase.Items.Count |
| 254 | + ) |
| 255 | + { |
| 256 | + ListViewBase.SelectedIndex = newIndex; |
| 257 | + StartRenameItem(); |
| 258 | + } |
| 259 | + } |
| 260 | + |
| 261 | + e.Handled = true; |
| 262 | + break; |
204 | 263 | } |
205 | | - else if (e.Key == VirtualKey.Enter) |
| 264 | + } |
| 265 | + |
| 266 | + protected bool TryStartRenameNextItem(ListedItem item) |
| 267 | + { |
| 268 | + var nextItemIndex = ListViewBase.Items.IndexOf(item) + NextRenameIndex; |
| 269 | + NextRenameIndex = 0; |
| 270 | + |
| 271 | + if |
| 272 | + ( |
| 273 | + nextItemIndex >= 0 && |
| 274 | + nextItemIndex < ListViewBase.Items.Count |
| 275 | + ) |
206 | 276 | { |
207 | | - TextBox textBox = (TextBox)sender; |
208 | | - textBox.LostFocus -= RenameTextBox_LostFocus; |
209 | | - CommitRename(textBox); |
210 | | - e.Handled = true; |
| 277 | + ListViewBase.SelectedIndex = nextItemIndex; |
| 278 | + StartRenameItem(); |
| 279 | + |
| 280 | + return true; |
211 | 281 | } |
| 282 | + |
| 283 | + return false; |
212 | 284 | } |
213 | 285 |
|
214 | 286 | protected override void Page_CharacterReceived(UIElement sender, CharacterReceivedRoutedEventArgs args) |
@@ -237,5 +309,8 @@ public override void Dispose() |
237 | 309 | UnhookEvents(); |
238 | 310 | CommandsViewModel?.Dispose(); |
239 | 311 | } |
| 312 | + |
| 313 | + [DllImport("User32.dll")] |
| 314 | + private extern static short GetKeyState(int n); |
240 | 315 | } |
241 | 316 | } |
0 commit comments