Update the KBM UI to use a Grid based layout rather than stack panels (#2299)
* Added grid to edit keyboard * Fixed all issues for Edit keyboard window with grid * Added step to delete row definition and move row indices * Handled grid operations for Edit Shortcuts * Added dynamic layout for edit shortcuts * Fixed resize windows message behaviour and removed warnings
This commit is contained in:
parent
32ddf3246c
commit
b5bd2df814
8 changed files with 327 additions and 232 deletions
|
@ -77,20 +77,20 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
|||
Windows::UI::Xaml::Controls::StackPanel xamlContainer;
|
||||
|
||||
// Header for the window
|
||||
Windows::UI::Xaml::Controls::StackPanel header;
|
||||
header.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||
Windows::UI::Xaml::Controls::RelativePanel header;
|
||||
header.Margin({ 10, 10, 10, 30 });
|
||||
header.Spacing(10);
|
||||
|
||||
// Header text
|
||||
TextBlock headerText;
|
||||
headerText.Text(L"Remap Keyboard");
|
||||
headerText.FontSize(30);
|
||||
headerText.Margin({ 0, 0, 1000, 0 });
|
||||
headerText.Margin({ 0, 0, 0, 0 });
|
||||
header.SetAlignLeftWithPanel(headerText, true);
|
||||
|
||||
// Header Cancel button
|
||||
Button cancelButton;
|
||||
cancelButton.Content(winrt::box_value(L"Cancel"));
|
||||
cancelButton.Margin({ 0, 0, 10, 0 });
|
||||
cancelButton.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
// Close the window since settings do not need to be saved
|
||||
PostMessage(_hWndEditKeyboardWindow, WM_CLOSE, 0, 0);
|
||||
|
@ -102,30 +102,37 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
|||
keyRemapInfoHeader.Margin({ 10, 0, 0, 10 });
|
||||
|
||||
// Table to display the key remaps
|
||||
Windows::UI::Xaml::Controls::StackPanel keyRemapTable;
|
||||
Grid keyRemapTable;
|
||||
ColumnDefinition firstColumn;
|
||||
ColumnDefinition secondColumn;
|
||||
ColumnDefinition thirdColumn;
|
||||
keyRemapTable.Margin({ 10, 10, 10, 20 });
|
||||
keyRemapTable.Spacing(10);
|
||||
|
||||
// Header row of the keys remap table
|
||||
Windows::UI::Xaml::Controls::StackPanel tableHeaderRow;
|
||||
tableHeaderRow.Spacing(100);
|
||||
tableHeaderRow.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||
keyRemapTable.HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||
keyRemapTable.ColumnSpacing(10);
|
||||
keyRemapTable.ColumnDefinitions().Append(firstColumn);
|
||||
keyRemapTable.ColumnDefinitions().Append(secondColumn);
|
||||
keyRemapTable.ColumnDefinitions().Append(thirdColumn);
|
||||
keyRemapTable.RowDefinitions().Append(RowDefinition());
|
||||
|
||||
// First header textblock in the header row of the keys remap table
|
||||
TextBlock originalKeyRemapHeader;
|
||||
originalKeyRemapHeader.Text(L"Original Key:");
|
||||
originalKeyRemapHeader.FontWeight(Text::FontWeights::Bold());
|
||||
originalKeyRemapHeader.Margin({ 0, 0, 0, 10 });
|
||||
tableHeaderRow.Children().Append(originalKeyRemapHeader);
|
||||
|
||||
// Second header textblock in the header row of the keys remap table
|
||||
TextBlock newKeyRemapHeader;
|
||||
newKeyRemapHeader.Text(L"New Key:");
|
||||
newKeyRemapHeader.FontWeight(Text::FontWeights::Bold());
|
||||
newKeyRemapHeader.Margin({ 0, 0, 0, 10 });
|
||||
tableHeaderRow.Children().Append(newKeyRemapHeader);
|
||||
|
||||
keyRemapTable.Children().Append(tableHeaderRow);
|
||||
keyRemapTable.SetColumn(originalKeyRemapHeader, 0);
|
||||
keyRemapTable.SetRow(originalKeyRemapHeader, 0);
|
||||
keyRemapTable.SetColumn(newKeyRemapHeader, 1);
|
||||
keyRemapTable.SetRow(newKeyRemapHeader, 0);
|
||||
|
||||
keyRemapTable.Children().Append(originalKeyRemapHeader);
|
||||
keyRemapTable.Children().Append(newKeyRemapHeader);
|
||||
|
||||
// Message to display success/failure of saving settings.
|
||||
Flyout applyFlyout;
|
||||
|
@ -197,6 +204,8 @@ void createEditKeyboardWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMan
|
|||
// Main Header Apply button
|
||||
Button applyButton;
|
||||
applyButton.Content(winrt::box_value(L"Apply"));
|
||||
header.SetAlignRightWithPanel(applyButton, true);
|
||||
header.SetLeftOf(cancelButton, applyButton);
|
||||
applyButton.Flyout(applyFlyout);
|
||||
applyButton.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
bool isSuccess = true;
|
||||
|
@ -315,7 +324,9 @@ LRESULT CALLBACK EditKeyboardWindowProc(HWND hWnd, UINT messageCode, WPARAM wPar
|
|||
RECT rcClient;
|
||||
switch (messageCode)
|
||||
{
|
||||
// Resize the XAML window whenever the parent window is painted or resized
|
||||
case WM_PAINT:
|
||||
case WM_SIZE:
|
||||
GetClientRect(hWnd, &rcClient);
|
||||
SetWindowPos(hWndXamlIslandEditKeyboardWindow, 0, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom, SWP_SHOWWINDOW);
|
||||
break;
|
||||
|
|
|
@ -78,50 +78,57 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
|||
Windows::UI::Xaml::Controls::StackPanel xamlContainer;
|
||||
|
||||
// Header for the window
|
||||
Windows::UI::Xaml::Controls::StackPanel header;
|
||||
header.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||
Windows::UI::Xaml::Controls::RelativePanel header;
|
||||
header.Margin({ 10, 10, 10, 30 });
|
||||
header.Spacing(10);
|
||||
|
||||
// Header text
|
||||
TextBlock headerText;
|
||||
headerText.Text(L"Edit Shortcuts");
|
||||
headerText.FontSize(30);
|
||||
headerText.Margin({ 0, 0, 100, 0 });
|
||||
header.SetAlignLeftWithPanel(headerText, true);
|
||||
|
||||
// Cancel button
|
||||
Button cancelButton;
|
||||
cancelButton.Content(winrt::box_value(L"Cancel"));
|
||||
cancelButton.Margin({ 0, 0, 10, 0 });
|
||||
cancelButton.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
// Close the window since settings do not need to be saved
|
||||
PostMessage(_hWndEditShortcutsWindow, WM_CLOSE, 0, 0);
|
||||
});
|
||||
|
||||
// Table to display the shortcuts
|
||||
Windows::UI::Xaml::Controls::StackPanel shortcutTable;
|
||||
Windows::UI::Xaml::Controls::Grid shortcutTable;
|
||||
ColumnDefinition firstColumn;
|
||||
ColumnDefinition secondColumn;
|
||||
ColumnDefinition thirdColumn;
|
||||
shortcutTable.Margin({ 10, 10, 10, 20 });
|
||||
shortcutTable.Spacing(10);
|
||||
|
||||
// Header row of the shortcut table
|
||||
Windows::UI::Xaml::Controls::StackPanel tableHeaderRow;
|
||||
tableHeaderRow.Spacing(100);
|
||||
tableHeaderRow.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||
shortcutTable.HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||
shortcutTable.ColumnSpacing(10);
|
||||
shortcutTable.ColumnDefinitions().Append(firstColumn);
|
||||
shortcutTable.ColumnDefinitions().Append(secondColumn);
|
||||
shortcutTable.ColumnDefinitions().Append(thirdColumn);
|
||||
shortcutTable.RowDefinitions().Append(RowDefinition());
|
||||
|
||||
// First header textblock in the header row of the shortcut table
|
||||
TextBlock originalShortcutHeader;
|
||||
originalShortcutHeader.Text(L"Original Shortcut:");
|
||||
originalShortcutHeader.FontWeight(Text::FontWeights::Bold());
|
||||
originalShortcutHeader.Margin({ 0, 0, 0, 10 });
|
||||
tableHeaderRow.Children().Append(originalShortcutHeader);
|
||||
|
||||
// Second header textblock in the header row of the shortcut table
|
||||
TextBlock newShortcutHeader;
|
||||
newShortcutHeader.Text(L"New Shortcut:");
|
||||
newShortcutHeader.FontWeight(Text::FontWeights::Bold());
|
||||
newShortcutHeader.Margin({ 0, 0, 0, 10 });
|
||||
tableHeaderRow.Children().Append(newShortcutHeader);
|
||||
|
||||
shortcutTable.Children().Append(tableHeaderRow);
|
||||
shortcutTable.SetColumn(originalShortcutHeader, 0);
|
||||
shortcutTable.SetRow(newShortcutHeader, 0);
|
||||
shortcutTable.SetColumn(originalShortcutHeader, 1);
|
||||
shortcutTable.SetRow(newShortcutHeader, 0);
|
||||
|
||||
shortcutTable.Children().Append(originalShortcutHeader);
|
||||
shortcutTable.Children().Append(newShortcutHeader);
|
||||
|
||||
// Message to display success/failure of saving settings.
|
||||
Flyout applyFlyout;
|
||||
|
@ -149,6 +156,8 @@ void createEditShortcutsWindow(HINSTANCE hInst, KeyboardManagerState& keyboardMa
|
|||
// Apply button
|
||||
Button applyButton;
|
||||
applyButton.Content(winrt::box_value(L"Apply"));
|
||||
header.SetAlignRightWithPanel(applyButton, true);
|
||||
header.SetLeftOf(cancelButton, applyButton);
|
||||
applyButton.Flyout(applyFlyout);
|
||||
applyButton.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
bool isSuccess = true;
|
||||
|
@ -239,7 +248,9 @@ LRESULT CALLBACK EditShortcutsWindowProc(HWND hWnd, UINT messageCode, WPARAM wPa
|
|||
RECT rcClient;
|
||||
switch (messageCode)
|
||||
{
|
||||
// Resize the XAML window whenever the parent window is painted or resized
|
||||
case WM_PAINT:
|
||||
case WM_SIZE:
|
||||
GetClientRect(hWnd, &rcClient);
|
||||
SetWindowPos(hWndXamlIslandEditShortcutsWindow, 0, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom, SWP_SHOWWINDOW);
|
||||
break;
|
||||
|
|
|
@ -36,6 +36,178 @@ void KeyDropDownControl::CheckAndUpdateKeyboardLayout(ComboBox currentDropDown,
|
|||
}
|
||||
}
|
||||
|
||||
// Function to set selection handler for single key remap drop down. Needs to be called after the constructor since the singleKeyControl StackPanel is null if called in the constructor
|
||||
void KeyDropDownControl::SetSelectionHandler(Grid& table, StackPanel& singleKeyControl, size_t colIndex, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer)
|
||||
{
|
||||
dropDown.SelectionChanged([&, table, singleKeyControl, colIndex](winrt::Windows::Foundation::IInspectable const& sender, SelectionChangedEventArgs const& args) {
|
||||
ComboBox currentDropDown = sender.as<ComboBox>();
|
||||
int selectedKeyIndex = currentDropDown.SelectedIndex();
|
||||
// Get row index of the single key control
|
||||
uint32_t controlIndex;
|
||||
bool indexFound = table.Children().IndexOf(singleKeyControl, controlIndex);
|
||||
if (indexFound)
|
||||
{
|
||||
int rowIndex = (controlIndex - 2) / 3;
|
||||
// Check if the element was not found or the index exceeds the known keys
|
||||
if (selectedKeyIndex != -1 && keyCodeList.size() > selectedKeyIndex)
|
||||
{
|
||||
singleKeyRemapBuffer[rowIndex][colIndex] = keyCodeList[selectedKeyIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset to null if the key is not found
|
||||
singleKeyRemapBuffer[rowIndex][colIndex] = NULL;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Function to set selection handler for shortcut drop down. Needs to be called after the constructor since the shortcutControl StackPanel is null if called in the constructor
|
||||
void KeyDropDownControl::SetSelectionHandler(Grid& table, StackPanel& shortcutControl, StackPanel parent, size_t colIndex, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects)
|
||||
{
|
||||
Flyout warningFlyout;
|
||||
TextBlock warningMessage;
|
||||
warningFlyout.Content(warningMessage);
|
||||
dropDown.ContextFlyout().SetAttachedFlyout((FrameworkElement)dropDown, warningFlyout);
|
||||
|
||||
// drop down selection handler
|
||||
dropDown.SelectionChanged([&, table, shortcutControl, colIndex, parent, warningMessage](winrt::Windows::Foundation::IInspectable const& sender, SelectionChangedEventArgs const&) {
|
||||
ComboBox currentDropDown = sender.as<ComboBox>();
|
||||
int selectedKeyIndex = currentDropDown.SelectedIndex();
|
||||
uint32_t dropDownIndex = -1;
|
||||
bool dropDownFound = parent.Children().IndexOf(currentDropDown, dropDownIndex);
|
||||
// Get row index of the single key control
|
||||
uint32_t controlIndex;
|
||||
bool controlIindexFound = table.Children().IndexOf(shortcutControl, controlIndex);
|
||||
|
||||
if (controlIindexFound)
|
||||
{
|
||||
int rowIndex = (controlIndex - 2) / 3;
|
||||
if (selectedKeyIndex != -1 && keyCodeList.size() > selectedKeyIndex && dropDownFound)
|
||||
{
|
||||
// If only 1 drop down and action key is chosen: Warn that a modifier must be chosen
|
||||
if (parent.Children().Size() == 1 && !KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex]))
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must start with a modifier key");
|
||||
}
|
||||
// If it is the last drop down
|
||||
else if (dropDownIndex == parent.Children().Size() - 1)
|
||||
{
|
||||
// If last drop down and a modifier is selected: add a new drop down (max of 5 drop downs should be enforced)
|
||||
if (KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex]) && parent.Children().Size() < 5)
|
||||
{
|
||||
// If it matched any of the previous modifiers then reset that drop down
|
||||
if (CheckRepeatedModifier(parent, dropDownIndex, selectedKeyIndex, keyCodeList))
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut cannot contain a repeated modifier");
|
||||
}
|
||||
// If not, add a new drop down
|
||||
else
|
||||
{
|
||||
AddDropDown(table, shortcutControl, parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects);
|
||||
}
|
||||
}
|
||||
// If last drop down and a modifier is selected but there are already 5 drop downs: warn the user
|
||||
else if (KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex]) && parent.Children().Size() >= 5)
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must contain an action key");
|
||||
}
|
||||
// If None is selected but it's the last index: warn
|
||||
else if (keyCodeList[selectedKeyIndex] == 0)
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must contain an action key");
|
||||
}
|
||||
// If none of the above, then the action key will be set
|
||||
}
|
||||
// If it is the not the last drop down
|
||||
else
|
||||
{
|
||||
if (KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex]))
|
||||
{
|
||||
// If it matched any of the previous modifiers then reset that drop down
|
||||
if (CheckRepeatedModifier(parent, dropDownIndex, selectedKeyIndex, keyCodeList))
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut cannot contain a repeated modifier");
|
||||
}
|
||||
// If not, the modifier key will be set
|
||||
}
|
||||
// If None is selected and there are more than 2 drop downs
|
||||
else if (keyCodeList[selectedKeyIndex] == 0 && parent.Children().Size() > 2)
|
||||
{
|
||||
// delete drop down
|
||||
parent.Children().RemoveAt(dropDownIndex);
|
||||
// delete drop down control object from the vector so that it can be destructed
|
||||
keyDropDownControlObjects.erase(keyDropDownControlObjects.begin() + dropDownIndex);
|
||||
parent.UpdateLayout();
|
||||
}
|
||||
else if (keyCodeList[selectedKeyIndex] == 0 && parent.Children().Size() <= 2)
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must have atleast 2 keys");
|
||||
}
|
||||
// If the user tries to set an action key check if all drop down menus after this are empty if it is not the first key
|
||||
else if (dropDownIndex != 0)
|
||||
{
|
||||
bool isClear = true;
|
||||
for (int i = dropDownIndex + 1; i < (int)parent.Children().Size(); i++)
|
||||
{
|
||||
ComboBox currentDropDown = parent.Children().GetAt(i).as<ComboBox>();
|
||||
if (currentDropDown.SelectedIndex() != -1)
|
||||
{
|
||||
isClear = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isClear)
|
||||
{
|
||||
// remove all the drop down
|
||||
int elementsToBeRemoved = parent.Children().Size() - dropDownIndex - 1;
|
||||
for (int i = 0; i < elementsToBeRemoved; i++)
|
||||
{
|
||||
parent.Children().RemoveAtEnd();
|
||||
keyDropDownControlObjects.erase(keyDropDownControlObjects.end() - 1);
|
||||
}
|
||||
parent.UpdateLayout();
|
||||
}
|
||||
else
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut cannot have more than one action key");
|
||||
}
|
||||
}
|
||||
// If there an action key is chosen on the first drop down and there are more than one drop down menus
|
||||
else
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must start with a modifier key");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the buffer based on the new selected drop down items
|
||||
shortcutRemapBuffer[rowIndex][colIndex].SetKeyCodes(GetKeysFromStackPanel(parent));
|
||||
}
|
||||
|
||||
// If the user searches for a key the selection handler gets invoked however if they click away it reverts back to the previous state. This can result in dangling references to added drop downs which were then reset.
|
||||
// We handle this by removing the drop down if it no longer a child of the parent
|
||||
for (long long i = keyDropDownControlObjects.size() - 1; i >= 0; i--)
|
||||
{
|
||||
uint32_t index;
|
||||
bool found = parent.Children().IndexOf(keyDropDownControlObjects[i]->GetComboBox(), index);
|
||||
if (!found)
|
||||
{
|
||||
keyDropDownControlObjects.erase(keyDropDownControlObjects.begin() + i);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Function to set the selected index of the drop down
|
||||
void KeyDropDownControl::SetSelectedIndex(int32_t index)
|
||||
{
|
||||
|
@ -49,14 +221,15 @@ ComboBox KeyDropDownControl::GetComboBox()
|
|||
}
|
||||
|
||||
// Function to add a drop down to the shortcut stack panel
|
||||
void KeyDropDownControl::AddDropDown(StackPanel parent, const size_t rowIndex, const size_t colIndex, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects)
|
||||
void KeyDropDownControl::AddDropDown(Grid table, StackPanel shortcutControl, StackPanel parent, const size_t colIndex, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects)
|
||||
{
|
||||
keyDropDownControlObjects.push_back(std::move(std::unique_ptr<KeyDropDownControl>(new KeyDropDownControl(rowIndex, colIndex, shortcutRemapBuffer, keyDropDownControlObjects, parent))));
|
||||
keyDropDownControlObjects.push_back(std::move(std::unique_ptr<KeyDropDownControl>(new KeyDropDownControl(true))));
|
||||
// Flyout to display the warning on the drop down element
|
||||
Flyout warningFlyout;
|
||||
TextBlock warningMessage;
|
||||
warningFlyout.Content(warningMessage);
|
||||
parent.Children().Append(keyDropDownControlObjects[keyDropDownControlObjects.size() - 1]->GetComboBox());
|
||||
keyDropDownControlObjects[keyDropDownControlObjects.size() - 1]->SetSelectionHandler(table, shortcutControl, parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects);
|
||||
parent.UpdateLayout();
|
||||
}
|
||||
|
||||
|
|
|
@ -23,152 +23,16 @@ public:
|
|||
static KeyboardManagerState* keyboardManagerState;
|
||||
|
||||
// Constructor for single key drop down
|
||||
KeyDropDownControl(size_t rowIndex, size_t colIndex, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer)
|
||||
KeyDropDownControl(bool isShortcut)
|
||||
{
|
||||
SetDefaultProperties(false);
|
||||
dropDown.SelectionChanged([&, rowIndex, colIndex](winrt::Windows::Foundation::IInspectable const& sender, SelectionChangedEventArgs const& args) {
|
||||
ComboBox currentDropDown = sender.as<ComboBox>();
|
||||
int selectedKeyIndex = currentDropDown.SelectedIndex();
|
||||
|
||||
// Check if the element was not found or the index exceeds the known keys
|
||||
if (selectedKeyIndex != -1 && keyCodeList.size() > selectedKeyIndex)
|
||||
{
|
||||
singleKeyRemapBuffer[rowIndex][colIndex] = keyCodeList[selectedKeyIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset to null if the key is not found
|
||||
singleKeyRemapBuffer[rowIndex][colIndex] = NULL;
|
||||
}
|
||||
});
|
||||
SetDefaultProperties(isShortcut);
|
||||
}
|
||||
|
||||
// Constructor for shortcut drop down
|
||||
KeyDropDownControl(size_t rowIndex, size_t colIndex, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects, StackPanel parent)
|
||||
{
|
||||
SetDefaultProperties(true);
|
||||
Flyout warningFlyout;
|
||||
TextBlock warningMessage;
|
||||
warningFlyout.Content(warningMessage);
|
||||
dropDown.ContextFlyout().SetAttachedFlyout((FrameworkElement)dropDown, warningFlyout);
|
||||
// Function to set selection handler for single key remap drop down. Needs to be called after the constructor since the singleKeyControl StackPanel is null if called in the constructor
|
||||
void SetSelectionHandler(Grid& table, StackPanel& singleKeyControl, size_t colIndex, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer);
|
||||
|
||||
// drop down selection handler
|
||||
dropDown.SelectionChanged([&, rowIndex, colIndex, parent, warningMessage](winrt::Windows::Foundation::IInspectable const& sender, SelectionChangedEventArgs const&) {
|
||||
ComboBox currentDropDown = sender.as<ComboBox>();
|
||||
int selectedKeyIndex = currentDropDown.SelectedIndex();
|
||||
uint32_t dropDownIndex = -1;
|
||||
bool dropDownFound = parent.Children().IndexOf(currentDropDown, dropDownIndex);
|
||||
|
||||
if (selectedKeyIndex != -1 && keyCodeList.size() > selectedKeyIndex && dropDownFound)
|
||||
{
|
||||
// If only 1 drop down and action key is chosen: Warn that a modifier must be chosen
|
||||
if (parent.Children().Size() == 1 && !KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex]))
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must start with a modifier key");
|
||||
}
|
||||
// If it is the last drop down
|
||||
else if (dropDownIndex == parent.Children().Size() - 1)
|
||||
{
|
||||
// If last drop down and a modifier is selected: add a new drop down (max of 5 drop downs should be enforced)
|
||||
if (KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex]) && parent.Children().Size() < 5)
|
||||
{
|
||||
// If it matched any of the previous modifiers then reset that drop down
|
||||
if (CheckRepeatedModifier(parent, dropDownIndex, selectedKeyIndex, keyCodeList))
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut cannot contain a repeated modifier");
|
||||
}
|
||||
// If not, add a new drop down
|
||||
else
|
||||
{
|
||||
AddDropDown(parent, rowIndex, colIndex, shortcutRemapBuffer, keyDropDownControlObjects);
|
||||
}
|
||||
}
|
||||
// If last drop down and a modifier is selected but there are already 5 drop downs: warn the user
|
||||
else if (KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex]) && parent.Children().Size() >= 5)
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must contain an action key");
|
||||
}
|
||||
// If None is selected but it's the last index: warn
|
||||
else if (keyCodeList[selectedKeyIndex] == 0)
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must contain an action key");
|
||||
}
|
||||
// If none of the above, then the action key will be set
|
||||
}
|
||||
// If it is the not the last drop down
|
||||
else
|
||||
{
|
||||
if (KeyboardManagerHelper::IsModifierKey(keyCodeList[selectedKeyIndex]))
|
||||
{
|
||||
// If it matched any of the previous modifiers then reset that drop down
|
||||
if (CheckRepeatedModifier(parent, dropDownIndex, selectedKeyIndex, keyCodeList))
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut cannot contain a repeated modifier");
|
||||
}
|
||||
// If not, the modifier key will be set
|
||||
}
|
||||
// If None is selected and there are more than 2 drop downs
|
||||
else if (keyCodeList[selectedKeyIndex] == 0 && parent.Children().Size() > 2)
|
||||
{
|
||||
// delete drop down
|
||||
parent.Children().RemoveAt(dropDownIndex);
|
||||
// delete drop down control object from the vector so that it can be destructed
|
||||
keyDropDownControlObjects.erase(keyDropDownControlObjects.begin() + dropDownIndex);
|
||||
parent.UpdateLayout();
|
||||
}
|
||||
else if (keyCodeList[selectedKeyIndex] == 0 && parent.Children().Size() <= 2)
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must have atleast 2 keys");
|
||||
}
|
||||
// If the user tries to set an action key check if all drop down menus after this are empty if it is not the first key
|
||||
else if (dropDownIndex != 0)
|
||||
{
|
||||
bool isClear = true;
|
||||
for (int i = dropDownIndex + 1; i < (int)parent.Children().Size(); i++)
|
||||
{
|
||||
ComboBox currentDropDown = parent.Children().GetAt(i).as<ComboBox>();
|
||||
if (currentDropDown.SelectedIndex() != -1)
|
||||
{
|
||||
isClear = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isClear)
|
||||
{
|
||||
// remove all the drop down
|
||||
int elementsToBeRemoved = parent.Children().Size() - dropDownIndex - 1;
|
||||
for (int i = 0; i < elementsToBeRemoved; i++)
|
||||
{
|
||||
parent.Children().RemoveAtEnd();
|
||||
}
|
||||
parent.UpdateLayout();
|
||||
}
|
||||
else
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut cannot have more than one action key");
|
||||
}
|
||||
}
|
||||
// If there an action key is chosen on the first drop down and there are more than one drop down menus
|
||||
else
|
||||
{
|
||||
// warn and reset the drop down
|
||||
SetDropDownError(currentDropDown, warningMessage, L"Shortcut must start with a modifier key");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the buffer based on the new selected drop down items
|
||||
shortcutRemapBuffer[rowIndex][colIndex].SetKeyCodes(GetKeysFromStackPanel(parent));
|
||||
});
|
||||
}
|
||||
// Function to set selection handler for shortcut drop down. Needs to be called after the constructor since the shortcutControl StackPanel is null if called in the constructor
|
||||
void SetSelectionHandler(Grid& table, StackPanel& shortcutControl, StackPanel parent, size_t colIndex, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects);
|
||||
|
||||
// Function to set the selected index of the drop down
|
||||
void SetSelectedIndex(int32_t index);
|
||||
|
@ -177,7 +41,7 @@ public:
|
|||
ComboBox GetComboBox();
|
||||
|
||||
// Function to add a drop down to the shortcut stack panel
|
||||
static void AddDropDown(StackPanel parent, const size_t rowIndex, const size_t colIndex, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects);
|
||||
static void AddDropDown(Grid table, StackPanel shortcutControl, StackPanel parent, const size_t colIndex, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, std::vector<std::unique_ptr<KeyDropDownControl>>& keyDropDownControlObjects);
|
||||
|
||||
// Function to get the list of key codes from the shortcut combo box stack panel
|
||||
std::vector<DWORD> GetKeysFromStackPanel(StackPanel parent);
|
||||
|
|
|
@ -9,22 +9,24 @@ KeyboardManagerState* ShortcutControl::keyboardManagerState = nullptr;
|
|||
std::vector<std::vector<Shortcut>> ShortcutControl::shortcutRemapBuffer;
|
||||
|
||||
// Function to add a new row to the shortcut table. If the originalKeys and newKeys args are provided, then the displayed shortcuts are set to those values.
|
||||
void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, Shortcut originalKeys, Shortcut newKeys)
|
||||
void ShortcutControl::AddNewShortcutControlRow(Grid& parent, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, Shortcut originalKeys, Shortcut newKeys)
|
||||
{
|
||||
// Parent element for the row
|
||||
Windows::UI::Xaml::Controls::StackPanel tableRow;
|
||||
tableRow.Spacing(100);
|
||||
tableRow.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||
|
||||
// Create new ShortcutControl objects dynamically so that we does not get destructed
|
||||
std::vector<std::unique_ptr<ShortcutControl>> newrow;
|
||||
newrow.push_back(std::move(std::unique_ptr<ShortcutControl>(new ShortcutControl(shortcutRemapBuffer.size(), 0))));
|
||||
newrow.push_back(std::move(std::unique_ptr<ShortcutControl>(new ShortcutControl(shortcutRemapBuffer.size(), 1))));
|
||||
newrow.push_back(std::move(std::unique_ptr<ShortcutControl>(new ShortcutControl(parent, 0))));
|
||||
newrow.push_back(std::move(std::unique_ptr<ShortcutControl>(new ShortcutControl(parent, 1))));
|
||||
keyboardRemapControlObjects.push_back(std::move(newrow));
|
||||
|
||||
// Add to grid
|
||||
parent.RowDefinitions().Append(RowDefinition());
|
||||
parent.SetColumn(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->getShortcutControl(), 0);
|
||||
parent.SetRow(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->getShortcutControl(), parent.RowDefinitions().Size() - 1);
|
||||
parent.SetColumn(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->getShortcutControl(), 1);
|
||||
parent.SetRow(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->getShortcutControl(), parent.RowDefinitions().Size() - 1);
|
||||
// ShortcutControl for the original shortcut
|
||||
tableRow.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->getShortcutControl());
|
||||
parent.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->getShortcutControl());
|
||||
// ShortcutControl for the new shortcut
|
||||
tableRow.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->getShortcutControl());
|
||||
parent.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->getShortcutControl());
|
||||
|
||||
// Delete row button
|
||||
Windows::UI::Xaml::Controls::Button deleteShortcut;
|
||||
|
@ -33,26 +35,41 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
|||
deleteSymbol.Glyph(L"\xE74D");
|
||||
deleteShortcut.Content(deleteSymbol);
|
||||
deleteShortcut.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
StackPanel currentRow = sender.as<Button>().Parent().as<StackPanel>();
|
||||
Button currentButton = sender.as<Button>();
|
||||
uint32_t index;
|
||||
parent.Children().IndexOf(currentRow, index);
|
||||
// Get index of delete button
|
||||
UIElementCollection children = parent.Children();
|
||||
children.IndexOf(currentButton, index);
|
||||
// Change the row index of elements appearing after the current row, as we will delete the row definition
|
||||
for (uint32_t i = index + 1; i < children.Size(); i++)
|
||||
{
|
||||
int32_t elementRowIndex = parent.GetRow(children.GetAt(i).as<FrameworkElement>());
|
||||
parent.SetRow(children.GetAt(i).as<FrameworkElement>(), elementRowIndex - 1);
|
||||
}
|
||||
parent.Children().RemoveAt(index);
|
||||
// delete the row from the buffer. Since first child of the stackpanel is the header, the effective index starts from 1
|
||||
shortcutRemapBuffer.erase(shortcutRemapBuffer.begin() + (index - 1));
|
||||
parent.Children().RemoveAt(index - 1);
|
||||
parent.Children().RemoveAt(index - 2);
|
||||
|
||||
// Calculate row index in the buffer from the grid child index (first two children are header elements and then three children in each row)
|
||||
int bufferIndex = (index - 2) / 3;
|
||||
// Delete the row definition
|
||||
parent.RowDefinitions().RemoveAt(bufferIndex + 1);
|
||||
// delete the row from the buffer
|
||||
shortcutRemapBuffer.erase(shortcutRemapBuffer.begin() + bufferIndex);
|
||||
// delete the ShortcutControl objects so that they get destructed
|
||||
keyboardRemapControlObjects.erase(keyboardRemapControlObjects.begin() + (index - 1));
|
||||
keyboardRemapControlObjects.erase(keyboardRemapControlObjects.begin() + bufferIndex);
|
||||
});
|
||||
tableRow.Children().Append(deleteShortcut);
|
||||
tableRow.UpdateLayout();
|
||||
parent.Children().Append(tableRow);
|
||||
parent.SetColumn(deleteShortcut, 2);
|
||||
parent.SetRow(deleteShortcut, parent.RowDefinitions().Size() - 1);
|
||||
parent.Children().Append(deleteShortcut);
|
||||
parent.UpdateLayout();
|
||||
|
||||
// Set the shortcut text if the two vectors are not empty (i.e. default args)
|
||||
if (originalKeys.IsValidShortcut() && newKeys.IsValidShortcut())
|
||||
{
|
||||
shortcutRemapBuffer.push_back(std::vector<Shortcut>{ Shortcut(), Shortcut() });
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->AddShortcutToControl(originalKeys, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->shortcutDropDownStackPanel, *keyboardManagerState, shortcutRemapBuffer.size() - 1, 0);
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->AddShortcutToControl(newKeys, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->shortcutDropDownStackPanel, *keyboardManagerState, shortcutRemapBuffer.size() - 1, 1);
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->AddShortcutToControl(originalKeys, parent, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->shortcutDropDownStackPanel, *keyboardManagerState, 0);
|
||||
keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->AddShortcutToControl(newKeys, parent, keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->shortcutDropDownStackPanel, *keyboardManagerState, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -62,7 +79,7 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
|||
}
|
||||
|
||||
// Function to add a shortcut to the shortcut control as combo boxes
|
||||
void ShortcutControl::AddShortcutToControl(Shortcut& shortcut, StackPanel parent, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex)
|
||||
void ShortcutControl::AddShortcutToControl(Shortcut& shortcut, Grid table, StackPanel parent, KeyboardManagerState& keyboardManagerState, const size_t colIndex)
|
||||
{
|
||||
// Delete the existing drop down menus
|
||||
parent.Children().Clear();
|
||||
|
@ -73,7 +90,7 @@ void ShortcutControl::AddShortcutToControl(Shortcut& shortcut, StackPanel parent
|
|||
std::vector<DWORD> keyCodeList = keyboardManagerState.keyboardMap.GetKeyCodeList(true);
|
||||
if (shortcutKeyCodes.size() != 0)
|
||||
{
|
||||
KeyDropDownControl::AddDropDown(parent, rowIndex, colIndex, shortcutRemapBuffer, keyDropDownControlObjects);
|
||||
KeyDropDownControl::AddDropDown(table, shortcutControlLayout, parent, colIndex, shortcutRemapBuffer, keyDropDownControlObjects);
|
||||
for (int i = 0; i < shortcutKeyCodes.size(); i++)
|
||||
{
|
||||
// New drop down gets added automatically when the SelectedIndex is set
|
||||
|
@ -98,7 +115,7 @@ StackPanel ShortcutControl::getShortcutControl()
|
|||
}
|
||||
|
||||
// Function to create the detect shortcut UI window
|
||||
void ShortcutControl::createDetectShortcutWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex)
|
||||
void ShortcutControl::createDetectShortcutWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t colIndex, Grid table)
|
||||
{
|
||||
// ContentDialog for detecting shortcuts. This is the parent UI element.
|
||||
ContentDialog detectShortcutBox;
|
||||
|
@ -130,15 +147,15 @@ void ShortcutControl::createDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
|||
&keyboardManagerState,
|
||||
&shortcutRemapBuffer,
|
||||
unregisterKeys,
|
||||
rowIndex,
|
||||
colIndex] {
|
||||
colIndex,
|
||||
table] {
|
||||
// Save the detected shortcut in the linked text block
|
||||
Shortcut detectedShortcutKeys = keyboardManagerState.GetDetectedShortcut();
|
||||
|
||||
if (!detectedShortcutKeys.IsEmpty())
|
||||
{
|
||||
// The shortcut buffer gets set in this function
|
||||
AddShortcutToControl(detectedShortcutKeys, linkedShortcutStackPanel, keyboardManagerState, rowIndex, colIndex);
|
||||
AddShortcutToControl(detectedShortcutKeys, table, linkedShortcutStackPanel, keyboardManagerState, colIndex);
|
||||
}
|
||||
|
||||
// Reset the keyboard manager UI state
|
||||
|
|
|
@ -29,17 +29,16 @@ public:
|
|||
// Vector to store dynamically allocated KeyDropDownControl objects to avoid early destruction
|
||||
std::vector<std::unique_ptr<KeyDropDownControl>> keyDropDownControlObjects;
|
||||
|
||||
ShortcutControl(const size_t rowIndex, const size_t colIndex)
|
||||
ShortcutControl(Grid table, const size_t colIndex)
|
||||
{
|
||||
shortcutDropDownStackPanel.Spacing(10);
|
||||
shortcutDropDownStackPanel.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||
KeyDropDownControl::AddDropDown(shortcutDropDownStackPanel, rowIndex, colIndex, shortcutRemapBuffer, keyDropDownControlObjects);
|
||||
|
||||
typeShortcut.Content(winrt::box_value(L"Type Shortcut"));
|
||||
typeShortcut.Click([&, rowIndex, colIndex](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
typeShortcut.Click([&, table, colIndex](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
keyboardManagerState->SetUIState(KeyboardManagerUIState::DetectShortcutWindowActivated, EditShortcutsWindowHandle);
|
||||
// Using the XamlRoot of the typeShortcut to get the root of the XAML host
|
||||
createDetectShortcutWindow(sender, sender.as<Button>().XamlRoot(), shortcutRemapBuffer, *keyboardManagerState, rowIndex, colIndex);
|
||||
createDetectShortcutWindow(sender, sender.as<Button>().XamlRoot(), shortcutRemapBuffer, *keyboardManagerState, colIndex, table);
|
||||
});
|
||||
|
||||
shortcutControlLayout.Margin({ 0, 0, 0, 10 });
|
||||
|
@ -47,18 +46,19 @@ public:
|
|||
|
||||
shortcutControlLayout.Children().Append(typeShortcut);
|
||||
shortcutControlLayout.Children().Append(shortcutDropDownStackPanel);
|
||||
KeyDropDownControl::AddDropDown(table, shortcutControlLayout, shortcutDropDownStackPanel, colIndex, shortcutRemapBuffer, keyDropDownControlObjects);
|
||||
shortcutControlLayout.UpdateLayout();
|
||||
}
|
||||
|
||||
// Function to add a new row to the shortcut table. If the originalKeys and newKeys args are provided, then the displayed shortcuts are set to those values.
|
||||
static void AddNewShortcutControlRow(StackPanel& parent, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, Shortcut originalKeys = Shortcut(), Shortcut newKeys = Shortcut());
|
||||
static void AddNewShortcutControlRow(Grid& parent, std::vector<std::vector<std::unique_ptr<ShortcutControl>>>& keyboardRemapControlObjects, Shortcut originalKeys = Shortcut(), Shortcut newKeys = Shortcut());
|
||||
|
||||
// Function to add a shortcut to the shortcut control as combo boxes
|
||||
void AddShortcutToControl(Shortcut& shortcut, StackPanel parent, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex);
|
||||
void AddShortcutToControl(Shortcut& shortcut, Grid table, StackPanel parent, KeyboardManagerState& keyboardManagerState, const size_t colIndex);
|
||||
|
||||
// Function to return the stack panel element of the ShortcutControl. This is the externally visible UI element which can be used to add it to other layouts
|
||||
StackPanel getShortcutControl();
|
||||
|
||||
// Function to create the detect shortcut UI window
|
||||
void createDetectShortcutWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex);
|
||||
void createDetectShortcutWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<Shortcut>>& shortcutRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t colIndex, Grid table);
|
||||
};
|
||||
|
|
|
@ -9,22 +9,25 @@ KeyboardManagerState* SingleKeyRemapControl::keyboardManagerState = nullptr;
|
|||
std::vector<std::vector<DWORD>> SingleKeyRemapControl::singleKeyRemapBuffer;
|
||||
|
||||
// Function to add a new row to the remap keys table. If the originalKey and newKey args are provided, then the displayed remap keys are set to those values.
|
||||
void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey, const DWORD newKey)
|
||||
void SingleKeyRemapControl::AddNewControlKeyRemapRow(Grid& parent, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey, const DWORD newKey)
|
||||
{
|
||||
// Parent element for the row
|
||||
Windows::UI::Xaml::Controls::StackPanel tableRow;
|
||||
tableRow.Spacing(100);
|
||||
tableRow.Orientation(Windows::UI::Xaml::Controls::Orientation::Horizontal);
|
||||
|
||||
// Create new SingleKeyRemapControl objects dynamically so that we does not get destructed
|
||||
std::vector<std::unique_ptr<SingleKeyRemapControl>> newrow;
|
||||
newrow.push_back(std::move(std::unique_ptr<SingleKeyRemapControl>(new SingleKeyRemapControl(singleKeyRemapBuffer.size(), 0))));
|
||||
newrow.push_back(std::move(std::unique_ptr<SingleKeyRemapControl>(new SingleKeyRemapControl(singleKeyRemapBuffer.size(), 1))));
|
||||
newrow.push_back(std::move(std::unique_ptr<SingleKeyRemapControl>(new SingleKeyRemapControl(parent, 0))));
|
||||
newrow.push_back(std::move(std::unique_ptr<SingleKeyRemapControl>(new SingleKeyRemapControl(parent, 1))));
|
||||
keyboardRemapControlObjects.push_back(std::move(newrow));
|
||||
|
||||
// Add to grid
|
||||
int debug = parent.RowDefinitions().Size();
|
||||
parent.RowDefinitions().Append(RowDefinition());
|
||||
parent.SetColumn(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->getSingleKeyRemapControl(), 0);
|
||||
parent.SetRow(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->getSingleKeyRemapControl(), parent.RowDefinitions().Size() - 1);
|
||||
parent.SetColumn(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->getSingleKeyRemapControl(), 1);
|
||||
parent.SetRow(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->getSingleKeyRemapControl(), parent.RowDefinitions().Size() - 1);
|
||||
// SingleKeyRemapControl for the original key.
|
||||
tableRow.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->getSingleKeyRemapControl());
|
||||
parent.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][0]->getSingleKeyRemapControl());
|
||||
// SingleKeyRemapControl for the new remap key
|
||||
tableRow.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->getSingleKeyRemapControl());
|
||||
parent.Children().Append(keyboardRemapControlObjects[keyboardRemapControlObjects.size() - 1][1]->getSingleKeyRemapControl());
|
||||
|
||||
// Set the key text if the two keys are not null (i.e. default args)
|
||||
if (originalKey != NULL && newKey != NULL)
|
||||
|
@ -55,17 +58,33 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::ve
|
|||
deleteSymbol.Glyph(L"\xE74D");
|
||||
deleteRemapKeys.Content(deleteSymbol);
|
||||
deleteRemapKeys.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
StackPanel currentRow = sender.as<Button>().Parent().as<StackPanel>();
|
||||
Button currentButton = sender.as<Button>();
|
||||
uint32_t index;
|
||||
parent.Children().IndexOf(currentRow, index);
|
||||
// Get index of delete button
|
||||
UIElementCollection children = parent.Children();
|
||||
children.IndexOf(currentButton, index);
|
||||
// Change the row index of elements appearing after the current row, as we will delete the row definition
|
||||
for (uint32_t i = index + 1; i < children.Size(); i++)
|
||||
{
|
||||
int32_t elementRowIndex = parent.GetRow(children.GetAt(i).as<FrameworkElement>());
|
||||
parent.SetRow(children.GetAt(i).as<FrameworkElement>(), elementRowIndex - 1);
|
||||
}
|
||||
parent.Children().RemoveAt(index);
|
||||
// delete the row from the buffer. Since first child of the stackpanel is the header, the effective index starts from 1
|
||||
singleKeyRemapBuffer.erase(singleKeyRemapBuffer.begin() + (index - 1));
|
||||
parent.Children().RemoveAt(index - 1);
|
||||
parent.Children().RemoveAt(index - 2);
|
||||
|
||||
// Calculate row index in the buffer from the grid child index (first two children are header elements and then three children in each row)
|
||||
int bufferIndex = (index - 2) / 3;
|
||||
// Delete the row definition
|
||||
parent.RowDefinitions().RemoveAt(bufferIndex + 1);
|
||||
// delete the row from the buffer.
|
||||
singleKeyRemapBuffer.erase(singleKeyRemapBuffer.begin() + bufferIndex);
|
||||
// delete the SingleKeyRemapControl objects so that they get destructed
|
||||
keyboardRemapControlObjects.erase(keyboardRemapControlObjects.begin() + (index - 1));
|
||||
keyboardRemapControlObjects.erase(keyboardRemapControlObjects.begin() + bufferIndex);
|
||||
});
|
||||
tableRow.Children().Append(deleteRemapKeys);
|
||||
parent.Children().Append(tableRow);
|
||||
parent.SetColumn(deleteRemapKeys, 2);
|
||||
parent.SetRow(deleteRemapKeys, parent.RowDefinitions().Size() - 1);
|
||||
parent.Children().Append(deleteRemapKeys);
|
||||
}
|
||||
|
||||
// Function to return the stack panel element of the SingleKeyRemapControl. This is the externally visible UI element which can be used to add it to other layouts
|
||||
|
@ -75,7 +94,7 @@ StackPanel SingleKeyRemapControl::getSingleKeyRemapControl()
|
|||
}
|
||||
|
||||
// Function to create the detect remap key UI window
|
||||
void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex)
|
||||
void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState)
|
||||
{
|
||||
// ContentDialog for detecting remap key. This is the parent UI element.
|
||||
ContentDialog detectRemapKeyBox;
|
||||
|
@ -100,9 +119,7 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
|||
detectRemapKeyBox,
|
||||
&keyboardManagerState,
|
||||
&singleKeyRemapBuffer,
|
||||
unregisterKeys,
|
||||
rowIndex,
|
||||
colIndex] {
|
||||
unregisterKeys] {
|
||||
// Save the detected key in the linked text block
|
||||
DWORD detectedKey = keyboardManagerState.GetDetectedSingleRemapKey();
|
||||
|
||||
|
|
|
@ -22,14 +22,14 @@ public:
|
|||
// Stores the current list of remappings
|
||||
static std::vector<std::vector<DWORD>> singleKeyRemapBuffer;
|
||||
|
||||
SingleKeyRemapControl(const size_t rowIndex, const size_t colIndex) :
|
||||
singleKeyRemapDropDown(rowIndex, colIndex, singleKeyRemapBuffer)
|
||||
SingleKeyRemapControl(Grid table, const size_t colIndex) :
|
||||
singleKeyRemapDropDown(false)
|
||||
{
|
||||
typeKey.Content(winrt::box_value(L"Type Key"));
|
||||
typeKey.Click([&, rowIndex, colIndex](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
typeKey.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
keyboardManagerState->SetUIState(KeyboardManagerUIState::DetectSingleKeyRemapWindowActivated, EditKeyboardWindowHandle);
|
||||
// Using the XamlRoot of the typeKey to get the root of the XAML host
|
||||
createDetectKeyWindow(sender, sender.as<Button>().XamlRoot(), singleKeyRemapBuffer, *keyboardManagerState, rowIndex, colIndex);
|
||||
createDetectKeyWindow(sender, sender.as<Button>().XamlRoot(), singleKeyRemapBuffer, *keyboardManagerState);
|
||||
});
|
||||
|
||||
singleKeyRemapControlLayout.Margin({ 0, 0, 0, 10 });
|
||||
|
@ -37,15 +37,17 @@ public:
|
|||
|
||||
singleKeyRemapControlLayout.Children().Append(typeKey);
|
||||
singleKeyRemapControlLayout.Children().Append(singleKeyRemapDropDown.GetComboBox());
|
||||
// Set selection handler for the drop down
|
||||
singleKeyRemapDropDown.SetSelectionHandler(table, singleKeyRemapControlLayout, colIndex, singleKeyRemapBuffer);
|
||||
singleKeyRemapControlLayout.UpdateLayout();
|
||||
}
|
||||
|
||||
// Function to add a new row to the remap keys table. If the originalKey and newKey args are provided, then the displayed remap keys are set to those values.
|
||||
static void AddNewControlKeyRemapRow(StackPanel& parent, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey = NULL, const DWORD newKey = NULL);
|
||||
static void AddNewControlKeyRemapRow(Grid& parent, std::vector<std::vector<std::unique_ptr<SingleKeyRemapControl>>>& keyboardRemapControlObjects, const DWORD originalKey = NULL, const DWORD newKey = NULL);
|
||||
|
||||
// Function to return the stack panel element of the SingleKeyRemapControl. This is the externally visible UI element which can be used to add it to other layouts
|
||||
StackPanel getSingleKeyRemapControl();
|
||||
|
||||
// Function to create the detect remap keys UI window
|
||||
void createDetectKeyWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState, const size_t rowIndex, const size_t colIndex);
|
||||
void createDetectKeyWindow(winrt::Windows::Foundation::IInspectable const& sender, XamlRoot xamlRoot, std::vector<std::vector<DWORD>>& singleKeyRemapBuffer, KeyboardManagerState& keyboardManagerState);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue