-
Notifications
You must be signed in to change notification settings - Fork 8.4k
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
Introduce search status #8588
Introduce search status #8588
Changes from 9 commits
fa06c6f
ff1558c
5391f4e
81a4a31
4ab4d41
4a2de19
fe59504
1068f85
8e5efb7
160716d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
#include "pch.h" | ||
#include "SearchBoxControl.h" | ||
#include "SearchBoxControl.g.cpp" | ||
#include <LibraryResources.h> | ||
|
||
using namespace winrt; | ||
using namespace winrt::Windows::UI::Xaml; | ||
|
@@ -18,12 +19,26 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation | |
|
||
this->CharacterReceived({ this, &SearchBoxControl::_CharacterHandler }); | ||
this->KeyDown({ this, &SearchBoxControl::_KeyDownHandler }); | ||
this->RegisterPropertyChangedCallback(UIElement::VisibilityProperty(), [this](auto&&, auto&&) { | ||
// Once the control is visible again we trigger SearchChanged event. | ||
// We do this since we probably have a value from the previous search, | ||
// and in such case logically the search changes from "nothing" to this value. | ||
// A good example for SearchChanged event consumer is Terminal Control. | ||
// Once the Search Box is open we want the Terminal Control | ||
// to immediately perform the search with the value appearing in the box. | ||
if (Visibility() == Visibility::Visible) | ||
{ | ||
_SearchChangedHandlers(TextBox().Text(), _GoForward(), _CaseSensitive()); | ||
} | ||
}); | ||
|
||
_focusableElements.insert(TextBox()); | ||
_focusableElements.insert(CloseButton()); | ||
_focusableElements.insert(CaseSensitivityButton()); | ||
_focusableElements.insert(GoForwardButton()); | ||
_focusableElements.insert(GoBackwardButton()); | ||
|
||
StatusBox().Width(_GetStatusMaxWidth()); | ||
} | ||
|
||
// Method Description: | ||
|
@@ -209,4 +224,143 @@ namespace winrt::Microsoft::Terminal::TerminalControl::implementation | |
{ | ||
e.Handled(true); | ||
} | ||
|
||
// Method Description: | ||
// - Handler for changing the text. Triggers SearchChanged event | ||
// Arguments: | ||
// - sender: not used | ||
// - e: event data | ||
// Return Value: | ||
// - <none> | ||
void SearchBoxControl::TextBoxTextChanged(winrt::Windows::Foundation::IInspectable const& /*sender*/, winrt::Windows::UI::Xaml::RoutedEventArgs const& /*e*/) | ||
{ | ||
_SearchChangedHandlers(TextBox().Text(), _GoForward(), _CaseSensitive()); | ||
} | ||
|
||
// Method Description: | ||
// - Handler for clicking the case sensitivity toggle. Triggers SearchChanged event | ||
// Arguments: | ||
// - sender: not used | ||
// - e: not used | ||
// Return Value: | ||
// - <none> | ||
void SearchBoxControl::CaseSensitivityButtonClicked(winrt::Windows::Foundation::IInspectable const& /*sender*/, winrt::Windows::UI::Xaml::RoutedEventArgs const& /*e*/) | ||
{ | ||
_SearchChangedHandlers(TextBox().Text(), _GoForward(), _CaseSensitive()); | ||
} | ||
|
||
// Method Description: | ||
// - Formats a status message representing the search state: | ||
// * "Searching" - if totalMatches is negative | ||
// * "No results" - if totalMatches is 0 | ||
// * "?/n" - if totalMatches=n matches and we didn't start the iteration over matches | ||
// (usually we will get this after buffer update) | ||
// * "m/n" - if we are currently at match m out of n. | ||
// * "m/max+" - if n > max results to show | ||
// * "?/max+" - if m > max results to show | ||
// Arguments: | ||
// - totalMatches - total number of matches (search results) | ||
// - currentMatch - the index of the current match (0-based) | ||
// Return Value: | ||
// - status message | ||
winrt::hstring SearchBoxControl::_FormatStatus(int32_t totalMatches, int32_t currentMatch) | ||
{ | ||
if (totalMatches < 0) | ||
{ | ||
return RS_(L"TermControl_Searching"); | ||
} | ||
|
||
if (totalMatches == 0) | ||
{ | ||
return RS_(L"TermControl_NoMatch"); | ||
} | ||
std::wstringstream ss; | ||
|
||
if (currentMatch < 0 || currentMatch > (MaximumTotalResultsToShowInStatus - 1)) | ||
{ | ||
ss << CurrentIndexTooHighStatus; | ||
} | ||
else | ||
{ | ||
ss << currentMatch + 1; | ||
} | ||
|
||
ss << StatusDelimiter; | ||
|
||
if (totalMatches > MaximumTotalResultsToShowInStatus) | ||
{ | ||
ss << TotalResultsTooHighStatus; | ||
} | ||
else | ||
{ | ||
ss << totalMatches; | ||
} | ||
|
||
return ss.str().data(); | ||
} | ||
|
||
// Method Description: | ||
// - Helper method to measure the width of the text block given the text and the font size | ||
// Arguments: | ||
// - text: the text to measure | ||
// - fontSize: the size of the font to measure | ||
// Return Value: | ||
// - the size in pixels | ||
double SearchBoxControl::_TextWidth(winrt::hstring text, double fontSize) | ||
{ | ||
auto t = winrt::Windows::UI::Xaml::Controls::TextBlock(); | ||
t.FontSize(fontSize); | ||
t.Text(text); | ||
t.Measure({ FLT_MAX, FLT_MAX }); | ||
return t.ActualWidth(); | ||
} | ||
|
||
// Method Description: | ||
// - This method tries to predict the maximal size of the status box | ||
// by measuring different possible statuses | ||
// Return Value: | ||
// - the size in pixels | ||
double SearchBoxControl::_GetStatusMaxWidth() | ||
{ | ||
const auto fontSize = StatusBox().FontSize(); | ||
const auto maxLength = std::max({ _TextWidth(_FormatStatus(-1, -1), fontSize), | ||
_TextWidth(_FormatStatus(0, -1), fontSize), | ||
_TextWidth(_FormatStatus(MaximumTotalResultsToShowInStatus, MaximumTotalResultsToShowInStatus - 1), fontSize), | ||
_TextWidth(_FormatStatus(MaximumTotalResultsToShowInStatus + 1, MaximumTotalResultsToShowInStatus - 1), fontSize), | ||
_TextWidth(_FormatStatus(MaximumTotalResultsToShowInStatus + 1, MaximumTotalResultsToShowInStatus), fontSize) }); | ||
|
||
return maxLength; | ||
} | ||
|
||
// Method Description: | ||
// - Formats and sets the status message in the status box. | ||
// Increases the size of the box if required. | ||
// Arguments: | ||
// - totalMatches - total number of matches (search results) | ||
// - currentMatch - the index of the current match (0-based) | ||
// Return Value: | ||
// - <none> | ||
void SearchBoxControl::SetStatus(int32_t totalMatches, int32_t currentMatch) | ||
{ | ||
const auto status = _FormatStatus(totalMatches, currentMatch); | ||
const auto requiredWidth = _TextWidth(status, StatusBox().FontSize()); | ||
if (requiredWidth > StatusBox().Width()) | ||
{ | ||
StatusBox().Width(requiredWidth); | ||
} | ||
Comment on lines
+347
to
+350
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like a complicated version of |
||
|
||
StatusBox().Text(status); | ||
} | ||
|
||
// Method Description: | ||
// - Enables / disables results navigation buttons | ||
// Arguments: | ||
// - enable: if true, the buttons should be enabled | ||
// Return Value: | ||
// - <none> | ||
void SearchBoxControl::SetNavigationEnabled(bool enabled) | ||
{ | ||
GoBackwardButton().IsEnabled(enabled); | ||
GoForwardButton().IsEnabled(enabled); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,7 +53,7 @@ | |
<SolidColorBrush x:Key="TextControlBorderBrushFocused" Color="#404040"/> | ||
<SolidColorBrush x:Key="TextControlButtonForegroundPressed" Color="#FFFFFF"/> | ||
<SolidColorBrush x:Key="TextControlButtonBackgroundPressed" Color="#FF4343"/> | ||
|
||
<!-- ToggleButton colors !--> | ||
<SolidColorBrush x:Key="ToggleButtonForeground" Color="#B5B5B5"/> | ||
|
||
|
@@ -161,8 +161,16 @@ | |
KeyDown="TextBoxKeyDown" | ||
Margin="5" | ||
HorizontalAlignment="Left" | ||
VerticalAlignment="Center"> | ||
VerticalAlignment="Center" | ||
TextChanged="TextBoxTextChanged"> | ||
</TextBox> | ||
<TextBlock x:Name="StatusBox" | ||
x:Uid="SearchBox_StatusBox" | ||
FontSize="15" | ||
Margin="5" | ||
HorizontalAlignment="Left" | ||
VerticalAlignment="Center"> | ||
</TextBlock> | ||
|
||
<ToggleButton x:Name="GoBackwardButton" | ||
x:Uid="SearchBox_SearchBackwards" | ||
|
@@ -181,7 +189,8 @@ | |
|
||
<ToggleButton x:Name="CaseSensitivityButton" | ||
x:Uid="SearchBox_CaseSensitivity" | ||
Style="{StaticResource ToggleButtonStyle}"> | ||
Style="{StaticResource ToggleButtonStyle}" | ||
Click="CaseSensitivityButtonClicked"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does this also trigger for keyboard activation? is there another event on ToggleButton that we can listen to for it being toggled? |
||
<PathIcon Data="M8.87305 10H7.60156L6.5625 7.25195H2.40625L1.42871 10H0.150391L3.91016 0.197266H5.09961L8.87305 10ZM6.18652 6.21973L4.64844 2.04297C4.59831 1.90625 4.54818 1.6875 4.49805 1.38672H4.4707C4.42513 1.66471 4.37272 1.88346 4.31348 2.04297L2.78906 6.21973H6.18652ZM15.1826 10H14.0615V8.90625H14.0342C13.5465 9.74479 12.8288 10.1641 11.8809 10.1641C11.1836 10.1641 10.6367 9.97949 10.2402 9.61035C9.84831 9.24121 9.65234 8.7513 9.65234 8.14062C9.65234 6.83268 10.4225 6.07161 11.9629 5.85742L14.0615 5.56348C14.0615 4.37402 13.5807 3.7793 12.6191 3.7793C11.776 3.7793 11.015 4.06641 10.3359 4.64062V3.49219C11.0241 3.05469 11.8171 2.83594 12.7148 2.83594C14.36 2.83594 15.1826 3.70638 15.1826 5.44727V10ZM14.0615 6.45898L12.373 6.69141C11.8535 6.76432 11.4616 6.89421 11.1973 7.08105C10.9329 7.26335 10.8008 7.58919 10.8008 8.05859C10.8008 8.40039 10.9215 8.68066 11.1631 8.89941C11.4092 9.11361 11.735 9.2207 12.1406 9.2207C12.6966 9.2207 13.1546 9.02702 13.5146 8.63965C13.8792 8.24772 14.0615 7.75326 14.0615 7.15625V6.45898Z"/> | ||
</ToggleButton> | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: whenever you find yourself writing
auto f = type();
, just prefertype f;
-- it's shorter and has a better information locality!