2019-07-09 23:47:30 +02:00
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
|
|
// Licensed under the MIT license.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "winrt/Microsoft.UI.Xaml.Controls.h"
|
|
|
|
|
|
|
|
#include "TerminalPage.g.h"
|
2019-09-04 23:34:06 +02:00
|
|
|
#include "Tab.h"
|
|
|
|
#include "CascadiaSettings.h"
|
|
|
|
#include "Profile.h"
|
|
|
|
|
|
|
|
#include <winrt/Microsoft.Terminal.TerminalControl.h>
|
|
|
|
#include <winrt/Microsoft.Terminal.TerminalConnection.h>
|
|
|
|
#include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h>
|
|
|
|
#include <winrt/Windows.ApplicationModel.DataTransfer.h>
|
|
|
|
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
|
2019-07-09 23:47:30 +02:00
|
|
|
|
|
|
|
namespace winrt::TerminalApp::implementation
|
|
|
|
{
|
|
|
|
struct TerminalPage : TerminalPageT<TerminalPage>
|
|
|
|
{
|
2019-09-04 23:34:06 +02:00
|
|
|
public:
|
2019-07-09 23:47:30 +02:00
|
|
|
TerminalPage();
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
void SetSettings(std::shared_ptr<::TerminalApp::CascadiaSettings> settings, bool needRefreshUI);
|
|
|
|
|
|
|
|
void Create();
|
|
|
|
|
|
|
|
hstring Title();
|
|
|
|
|
|
|
|
void ShowOkDialog(const winrt::hstring& titleKey, const winrt::hstring& contentKey);
|
|
|
|
|
|
|
|
void TitlebarClicked();
|
|
|
|
|
2019-10-11 02:09:07 +02:00
|
|
|
void CloseWindow();
|
|
|
|
|
2019-09-04 23:34:06 +02:00
|
|
|
// -------------------------------- WinRT Events ---------------------------------
|
|
|
|
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(TitleChanged, _titleChangeHandlers, winrt::Windows::Foundation::IInspectable, winrt::hstring);
|
|
|
|
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(LastTabClosed, _lastTabClosedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs);
|
|
|
|
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTitleBarContent, _setTitleBarContentHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::UIElement);
|
|
|
|
DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ShowDialog, _showDialogHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::Controls::ContentDialog);
|
|
|
|
|
|
|
|
private:
|
|
|
|
// If you add controls here, but forget to null them either here or in
|
|
|
|
// the ctor, you're going to have a bad time. It'll mysteriously fail to
|
|
|
|
// activate the app.
|
|
|
|
// ALSO: If you add any UIElements as roots here, make sure they're
|
|
|
|
// updated in App::_ApplyTheme. The roots currently is _tabRow
|
|
|
|
// (which is a root when the tabs are in the titlebar.)
|
|
|
|
Microsoft::UI::Xaml::Controls::TabView _tabView{ nullptr };
|
|
|
|
TerminalApp::TabRowControl _tabRow{ nullptr };
|
|
|
|
Windows::UI::Xaml::Controls::Grid _tabContent{ nullptr };
|
2019-10-15 07:41:43 +02:00
|
|
|
Microsoft::UI::Xaml::Controls::SplitButton _newTabButton{ nullptr };
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
std::shared_ptr<::TerminalApp::CascadiaSettings> _settings{ nullptr };
|
|
|
|
|
|
|
|
std::vector<std::shared_ptr<Tab>> _tabs;
|
|
|
|
|
|
|
|
void _ShowAboutDialog();
|
2019-09-17 07:43:27 +02:00
|
|
|
void _ShowCloseWarningDialog();
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
void _CreateNewTabFlyout();
|
|
|
|
void _OpenNewTabDropdown();
|
|
|
|
void _OpenNewTab(std::optional<int> profileIndex);
|
|
|
|
void _CreateNewTabFromSettings(GUID profileGuid, winrt::Microsoft::Terminal::Settings::TerminalSettings settings);
|
|
|
|
winrt::Microsoft::Terminal::TerminalConnection::ITerminalConnection _CreateConnectionFromSettings(GUID profileGuid, winrt::Microsoft::Terminal::Settings::TerminalSettings settings);
|
|
|
|
|
|
|
|
void _SettingsButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
|
|
|
|
void _FeedbackButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
|
|
|
|
void _AboutButtonOnClick(const IInspectable& sender, const Windows::UI::Xaml::RoutedEventArgs& eventArgs);
|
2019-09-17 07:43:27 +02:00
|
|
|
void _CloseWarningPrimaryButtonOnClick(Windows::UI::Xaml::Controls::ContentDialog sender, Windows::UI::Xaml::Controls::ContentDialogButtonClickEventArgs eventArgs);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
void _HookupKeyBindings(TerminalApp::AppKeyBindings bindings) noexcept;
|
|
|
|
|
|
|
|
void _UpdateTitle(std::shared_ptr<Tab> tab);
|
|
|
|
void _UpdateTabIcon(std::shared_ptr<Tab> tab);
|
|
|
|
void _UpdateTabView();
|
|
|
|
void _DuplicateTabViewItem();
|
2019-10-15 07:41:43 +02:00
|
|
|
void _RemoveTabViewItem(const Microsoft::UI::Xaml::Controls::TabViewItem& tabViewItem);
|
2019-09-17 07:43:27 +02:00
|
|
|
void _RemoveTabViewItemByIndex(uint32_t tabIndex);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
void _RegisterTerminalEvents(Microsoft::Terminal::TerminalControl::TermControl term, std::shared_ptr<Tab> hostingTab);
|
|
|
|
|
|
|
|
void _SelectNextTab(const bool bMoveRight);
|
|
|
|
bool _SelectTab(const int tabIndex);
|
|
|
|
void _MoveFocus(const Direction& direction);
|
|
|
|
|
|
|
|
winrt::Microsoft::Terminal::TerminalControl::TermControl _GetFocusedControl();
|
|
|
|
int _GetFocusedTabIndex() const;
|
|
|
|
void _SetFocusedTabIndex(int tabIndex);
|
|
|
|
void _CloseFocusedTab();
|
|
|
|
void _CloseFocusedPane();
|
2019-09-17 07:43:27 +02:00
|
|
|
void _CloseAllTabs();
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
// Todo: add more event implementations here
|
|
|
|
// MSFT:20641986: Add keybindings for New Window
|
|
|
|
void _Scroll(int delta);
|
|
|
|
void _SplitVertical(const std::optional<GUID>& profileGuid);
|
|
|
|
void _SplitHorizontal(const std::optional<GUID>& profileGuid);
|
|
|
|
void _SplitPane(const Pane::SplitState splitType, const std::optional<GUID>& profileGuid);
|
|
|
|
void _ResizePane(const Direction& direction);
|
|
|
|
void _ScrollPage(int delta);
|
|
|
|
void _SetAcceleratorForMenuItem(Windows::UI::Xaml::Controls::MenuFlyoutItem& menuItem, const winrt::Microsoft::Terminal::Settings::KeyChord& keyChord);
|
|
|
|
|
|
|
|
void _CopyToClipboardHandler(const IInspectable& sender, const winrt::Microsoft::Terminal::TerminalControl::CopyToClipboardEventArgs& copiedData);
|
|
|
|
void _PasteFromClipboardHandler(const IInspectable& sender,
|
|
|
|
const Microsoft::Terminal::TerminalControl::PasteFromClipboardEventArgs& eventArgs);
|
|
|
|
bool _CopyText(const bool trimTrailingWhitespace);
|
|
|
|
void _PasteText();
|
|
|
|
static fire_and_forget PasteFromClipboard(winrt::Microsoft::Terminal::TerminalControl::PasteFromClipboardEventArgs eventArgs);
|
|
|
|
|
Add Cascading User + Default Settings (#2515)
This PR represents the start of the work on Cascading User + default settings, #754.
Cascading settings will be done in two parts:
* [ ] Layered Default+User settings (this PR)
* [ ] Dynamic Profile Generation (#2603).
Until _both_ are done, _neither are going in. The dynamic profiles PR will target this PR when it's ready, but will go in as a separate commit into master.
This PR covers adding one primary feature: the settings are now in two separate files:
* a static `defaults.json` that ships with the package (the "default settings")
* a `profiles.json` with the user's customizations (the "user settings)
User settings are _layered_ upon the settings in the defaults settings.
## References
Other things that might be related here:
* #1378 - This seems like it's definitely fixed. The default keybindings are _much_ cleaner, and without the save-on-load behavior, the user's keybindings will be left in a good state
* #1398 - This might have honestly been solved by #2475
## PR Checklist
* [x] Closes #754
* [x] Closes #1378
* [x] Closes #2566
* [x] I work here
* [x] Tests added/passed
* [x] Requires documentation to be updated - it **ABSOLUTELY DOES**
## Detailed Description of the Pull Request / Additional comments
1. We start by taking all of the `FromJson` functions in Profile, ColorScheme, Globals, etc, and converting them to `LayerJson` methods. These are effectively the same, with the change that instead of building a new object, they are simply layering the values on top of `this` object.
2. Next, we add tests for layering properties like that.
3. Now, we add a `defaults.json` to the package. This is the file the users can refer to as our default settings.
4. We then take that `defaults.json` and stamp it into an auto generated `.h` file, so we can use it's data without having to worry about reading it from disk.
5. We then change the `LoadAll` function in `CascadiaSettings`. Now, the function does two loads - one from the defaults, and then a second load from the `profiles.json` file, layering the settings from each source upon the previous values.
6. If the `profiles.json` file doesn't exist, we'll create it from a hardcoded `userDefaults.json`, which is stamped in similar to how `defaults.json` is.
7. We also add support for _unbinding_ keybindings that might exist in the `defaults.json`, but the user doesn't want to be bound to anything.
8. We add support for _hiding_ a profile, which is useful if a user doesn't want one of the default profiles to appear in the list of profiles.
## TODO:
* [x] Still need to make Alt+Click work on the settings button
* [x] Need to write some user documentation on how the new settings model works
* [x] Fix the pair of tests I broke (re: Duplicate profiles)
<hr>
* Create profiles by layering them
* Update test to layer multiple times on the same profile
* Add support for layering an array of profiles, but break a couple tests
* Add a defaults.json to the package
* Layer colorschemes
* Moves tests into individual classes
* adds support for layering a colorscheme on top of another
* Layer an array of color schemes
* oh no, this was missed with #2481
must have committed without staging this change, uh oh. Not like those tests actually work so nbd
* Layer keybindings
* Read settings from defaults.json + profiles.json, layer appropriately
This is like 80% of #754. Needs tests.
* Add tests for keybindings
* add support to unbind a key with `null` or `"unbound"` or `"garbage"`
* Layer or clear optional properties
* Add a helper to get an optional variable for a bunch of different types
In the end, I think we need to ask _was this worth it_
* Do this with the stretch mode too
* Add back in the GUID check for profiles
* Add some tests for global settings layering
* M A D W I T H P O W E R
Add a MsBuild target to auto-generate a header with the defaults.json as a
string in the file. That way, we can _always_ load the defaults. Literally impossible to not.
* When the user's profile.json doesn't exist, create it from a template
* Re-order profiles to match the order set in the user's profiles.json
* Add tests for re-ordering profiles to match user ordering
* Add support for hiding profiles using `"hidden": true`
* Use the hardcoded defaults.json for the exception->"use defaults" case
* Somehow I messed up the git submodules?
* woo documentation
* Fix a Terminal.App.Unit.Tests failure
* signed/unsigned is hard
* Use Alt+Settings button to open the default settings
* Missed a signed/unsigned
* Some very preliminary PR feedback
* More PR feedback
Use the wil helper for the exe path
Move jsonutils into their own file
kill some dead code
* Add templates to these bois
* remove some code for generating defaults, reorder defaults.json a tad
* Make guid a std::optional
* Large block of PR feedback
* Remove some dead code
* add some comments
* tag some todos
* stl is love, stl is life
* add `-noprofile`
* Fix the crash that dustin found
* -Encoding ASCII
* Set a profile's default scheme to Campbell
* Fix the tests I regressed
* Update UsingJsonSetting.md to reflect that changes from these PRs
* Change how GenerateGuidForProfile works
* Make AppKeyBindings do its own serialization
* Remove leftover dead code from the previous commit
* Fix up an enormous number of PR nits
* Fix a typo; Update the defaults to match #2378
* Tiny nits
* Some typos, PR nits
* Fix this broken defaults case
2019-09-16 21:57:10 +02:00
|
|
|
fire_and_forget _LaunchSettings(const bool openDefaults);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
void _OnTabClick(const IInspectable& sender, const Windows::UI::Xaml::Input::PointerRoutedEventArgs& eventArgs);
|
|
|
|
void _OnTabSelectionChanged(const IInspectable& sender, const Windows::UI::Xaml::Controls::SelectionChangedEventArgs& eventArgs);
|
|
|
|
void _OnTabItemsChanged(const IInspectable& sender, const Windows::Foundation::Collections::IVectorChangedEventArgs& eventArgs);
|
|
|
|
void _OnContentSizeChanged(const IInspectable& /*sender*/, Windows::UI::Xaml::SizeChangedEventArgs const& e);
|
2019-10-15 07:41:43 +02:00
|
|
|
void _OnTabCloseRequested(const IInspectable& sender, const Microsoft::UI::Xaml::Controls::TabViewTabCloseRequestedEventArgs& eventArgs);
|
2019-09-04 23:34:06 +02:00
|
|
|
|
|
|
|
void _RefreshUIForSettingsReload();
|
|
|
|
|
|
|
|
#pragma region ActionHandlers
|
|
|
|
// These are all defined in AppActionHandlers.cpp
|
|
|
|
void _HandleNewTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleOpenNewTabDropdown(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleDuplicateTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleCloseTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleClosePane(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleScrollUp(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleScrollDown(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleNextTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandlePrevTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleSplitVertical(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleSplitHorizontal(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleScrollUpPage(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleScrollDownPage(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleOpenSettings(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandlePasteText(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleNewTabWithProfile(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleSwitchToTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleResizePane(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleMoveFocus(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
|
|
|
void _HandleCopyText(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
2019-09-17 07:43:27 +02:00
|
|
|
void _HandleCloseWindow(const IInspectable&, const TerminalApp::ActionEventArgs& args);
|
2019-09-30 15:18:05 +02:00
|
|
|
void _HandleAdjustFontSize(const IInspectable& sender, const TerminalApp::ActionEventArgs& args);
|
2019-09-04 23:34:06 +02:00
|
|
|
#pragma endregion
|
2019-07-09 23:47:30 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace winrt::TerminalApp::factory_implementation
|
|
|
|
{
|
|
|
|
struct TerminalPage : TerminalPageT<TerminalPage, implementation::TerminalPage>
|
|
|
|
{
|
|
|
|
};
|
|
|
|
}
|