- Moved the hotkey tester to an InputOverlay so it takes up less space

- Fixed bug where overlays may become obscured if a layout change happens
  in the background while one is visible.
- Added "SyncOnStartup" setting to SettingsLayout
This commit is contained in:
casey langen 2017-03-09 21:13:36 -08:00
parent ccee62cca5
commit b8a220e1dd
11 changed files with 96 additions and 22 deletions

View File

@ -37,6 +37,7 @@
#include <cursespp/App.h>
#include <cursespp/Colors.h>
#include <cursespp/DialogOverlay.h>
#include <cursespp/InputOverlay.h>
#include <cursespp/Screen.h>
#include <cursespp/SingleLineEntry.h>
@ -101,7 +102,11 @@ SettingsLayout::~SettingsLayout() {
}
void SettingsLayout::OnCheckboxChanged(cursespp::Checkbox* cb, bool checked) {
if (cb == removeCheckbox.get()) {
if (cb == syncOnStartupCheckbox.get()) {
this->libraryPrefs->SetBool(core::prefs::keys::SyncOnStartup, checked);
this->libraryPrefs->Save();
}
else if (cb == removeCheckbox.get()) {
this->libraryPrefs->SetBool(core::prefs::keys::RemoveMissingFiles, checked);
this->libraryPrefs->Save();
}
@ -152,6 +157,12 @@ void SettingsLayout::OnPluginsDropdownActivate(cursespp::TextLabel* label) {
PluginOverlay::Show();
}
void SettingsLayout::OnHotkeyDropdownActivate(cursespp::TextLabel* label) {
std::shared_ptr<InputOverlay> overlay(new InputOverlay());
overlay->SetTitle("hotkey tester").SetInputMode(IInput::InputRaw);
App::Overlays().Push(overlay);
}
void SettingsLayout::OnLayout() {
int x = this->GetX(), y = this->GetY();
int cx = this->GetWidth(), cy = this->GetHeight();
@ -175,12 +186,11 @@ void SettingsLayout::OnLayout() {
this->outputDropdown->MoveAndResize(1, y++, cx - 1, LABEL_HEIGHT);
this->transportDropdown->MoveAndResize(1, y++, cx - 1, LABEL_HEIGHT);
this->pluginsDropdown->MoveAndResize(1, y++, cx - 1, LABEL_HEIGHT);
this->hotkeyDropdown->MoveAndResize(1, y++, cx - 1, LABEL_HEIGHT);
this->dotfileCheckbox->MoveAndResize(1, y++, cx - 1, LABEL_HEIGHT);
this->syncOnStartupCheckbox->MoveAndResize(1, y++, cx - 1, LABEL_HEIGHT);
this->removeCheckbox->MoveAndResize(1, y++, cx - 1, LABEL_HEIGHT);
this->customColorsCheckbox->MoveAndResize(1, y++, cx - 1, LABEL_HEIGHT);
this->hotkeyLabel->MoveAndResize(1, y + 1, this->hotkeyLabel->Length(), LABEL_HEIGHT);
this->hotkeyInput->MoveAndResize(RIGHT(this->hotkeyLabel), y, HOTKEY_INPUT_WIDTH, INPUT_HEIGHT);
}
void SettingsLayout::RefreshAddedPaths() {
@ -249,23 +259,25 @@ void SettingsLayout::InitializeWindows() {
this->pluginsDropdown->SetText(arrow + " enable/disable plugins");
this->pluginsDropdown->Activated.connect(this, &SettingsLayout::OnPluginsDropdownActivate);
this->hotkeyDropdown.reset(new TextLabel());
this->hotkeyDropdown->SetText(arrow + " hotkey tester");
this->hotkeyDropdown->Activated.connect(this, &SettingsLayout::OnHotkeyDropdownActivate);
CREATE_CHECKBOX(this->dotfileCheckbox, "show dotfiles in directory browser");
CREATE_CHECKBOX(this->syncOnStartupCheckbox, "sync metadata on startup");
CREATE_CHECKBOX(this->removeCheckbox, "remove missing files from library");
CREATE_CHECKBOX(this->customColorsCheckbox, "disable custom colors (requires restart)");
this->hotkeyLabel.reset(new TextLabel());
this->hotkeyLabel->SetText("hotkey tester: ");
this->hotkeyInput.reset(new TextInput(IInput::InputRaw));
this->browseList->SetFocusOrder(0);
this->addedPathsList->SetFocusOrder(1);
this->outputDropdown->SetFocusOrder(2);
this->transportDropdown->SetFocusOrder(3);
this->pluginsDropdown->SetFocusOrder(4);
this->dotfileCheckbox->SetFocusOrder(5);
this->removeCheckbox->SetFocusOrder(6);
this->customColorsCheckbox->SetFocusOrder(7);
this->hotkeyInput->SetFocusOrder(8);
this->hotkeyDropdown->SetFocusOrder(5);
this->dotfileCheckbox->SetFocusOrder(6);
this->syncOnStartupCheckbox->SetFocusOrder(7);
this->removeCheckbox->SetFocusOrder(8);
this->customColorsCheckbox->SetFocusOrder(9);
this->AddWindow(this->browseLabel);
this->AddWindow(this->addedPathsLabel);
@ -274,11 +286,11 @@ void SettingsLayout::InitializeWindows() {
this->AddWindow(this->outputDropdown);
this->AddWindow(this->transportDropdown);
this->AddWindow(this->pluginsDropdown);
this->AddWindow(this->hotkeyDropdown);
this->AddWindow(this->dotfileCheckbox);
this->AddWindow(this->syncOnStartupCheckbox);
this->AddWindow(this->removeCheckbox);
this->AddWindow(this->customColorsCheckbox);
this->AddWindow(this->hotkeyLabel);
this->AddWindow(this->hotkeyInput);
}
void SettingsLayout::SetShortcutsWindow(ShortcutsWindow* shortcuts) {
@ -333,6 +345,7 @@ void SettingsLayout::CheckShowFirstRunDialog() {
}
void SettingsLayout::LoadPreferences() {
this->syncOnStartupCheckbox->SetChecked(this->libraryPrefs->GetBool(core::prefs::keys::SyncOnStartup, true));
this->removeCheckbox->SetChecked(this->libraryPrefs->GetBool(core::prefs::keys::RemoveMissingFiles, true));
this->customColorsCheckbox->SetChecked(this->libraryPrefs->GetBool(box::prefs::keys::DisableCustomColors));

View File

@ -97,6 +97,7 @@ namespace musik {
void OnOutputDropdownActivated(cursespp::TextLabel* label);
void OnTransportDropdownActivate(cursespp::TextLabel* label);
void OnPluginsDropdownActivate(cursespp::TextLabel* label);
void OnHotkeyDropdownActivate(cursespp::TextLabel* label);
int64 ListItemDecorator(
cursespp::ScrollableWindow* w,
@ -114,9 +115,11 @@ namespace musik {
std::shared_ptr<cursespp::TextLabel> outputDropdown;
std::shared_ptr<cursespp::TextLabel> transportDropdown;
std::shared_ptr<cursespp::TextLabel> pluginsDropdown;
std::shared_ptr<cursespp::TextLabel> hotkeyDropdown;
std::shared_ptr<cursespp::Checkbox> removeCheckbox;
std::shared_ptr<cursespp::Checkbox> dotfileCheckbox;
std::shared_ptr<cursespp::Checkbox> syncOnStartupCheckbox;
std::shared_ptr<cursespp::Checkbox> removeCheckbox;
std::shared_ptr<cursespp::Checkbox> customColorsCheckbox;
std::shared_ptr<cursespp::TextLabel> browseLabel;
@ -124,9 +127,6 @@ namespace musik {
std::shared_ptr<cursespp::ListWindow> browseList;
std::shared_ptr<cursespp::ListWindow> addedPathsList;
std::shared_ptr<cursespp::TextLabel> hotkeyLabel;
std::shared_ptr<cursespp::TextInput> hotkeyInput;
std::shared_ptr<cursespp::DialogOverlay> firstRunDialog;
std::shared_ptr<cursespp::SimpleScrollAdapter> addedPathsAdapter;

View File

@ -236,7 +236,14 @@ void App::Run(ILayoutPtr layout) {
because they may muck around with layout, then redraw the window. if
done in the reverse order, the user may observe more flicker. */
Window::MessageQueue().Dispatch();
Window::WriteToScreen(this->state.input);
if (Window::WriteToScreen(this->state.input)) {
/* if we wrote to the screen that means panels could have shifted
around. ensure any visible overlay is still on top. */
if (this->state.overlayWindow && !this->state.overlayWindow->IsTop()) {
this->state.overlay->BringToTop();
}
}
}
overlays.Clear();
@ -282,6 +289,9 @@ void App::CheckShowOverlay() {
this->state.overlay = top;
this->state.overlayWindow =
top ? dynamic_cast<IWindow*>(top.get()) : nullptr;
ILayoutPtr newTopLayout = this->state.ActiveLayout();
if (newTopLayout) {
newTopLayout->Layout();

View File

@ -68,12 +68,20 @@ namespace cursespp {
private:
struct WindowState {
ILayoutPtr overlay;
IWindow* overlayWindow;
ILayoutPtr layout;
IWindowPtr focused;
IViewRoot* viewRoot;
IInput* input;
IKeyHandler* keyHandler;
WindowState() {
this->overlayWindow = nullptr;
this->viewRoot = nullptr;
this->input = nullptr;
this->keyHandler = nullptr;
}
inline ILayoutPtr ActiveLayout() {
/* if there's a visible overlay, it's always the current
layout and will consume all key events */

View File

@ -83,6 +83,7 @@ namespace cursespp {
virtual bool IsVisible() = 0;
virtual bool IsFocused() = 0;
virtual void OnParentVisibilityChanged(bool visible) = 0;
virtual bool IsTop() = 0;
};
typedef std::shared_ptr<IWindow> IWindowPtr;

View File

@ -64,6 +64,7 @@ InputOverlay::InputOverlay() {
this->textInput->SetFocusedFrameColor(CURSESPP_OVERLAY_INPUT_FRAME);
this->textInput->SetFocusedContentColor(CURSESPP_OVERLAY_BACKGROUND);
this->textInput->EnterPressed.connect(this, &InputOverlay::OnInputEnterPressed);
this->textInput->TextChanged.connect(this, &InputOverlay::OnInputKeyPress);
this->AddWindow(this->textInput);
}
@ -114,6 +115,15 @@ InputOverlay& InputOverlay::SetWidth(int width) {
return *this;
}
void InputOverlay::OnInputKeyPress(TextInput* input, std::string key) {
/* raw input mode will not allow the ESC key to propagate.
we can catch it here, and pass it through to the regular key
handler to close the dialog */
if (input->GetInputMode() == IInput::InputRaw && key == "^[") {
this->KeyPress(key);
}
}
bool InputOverlay::KeyPress(const std::string& key) {
if (key == "^[") { /* esc closes */
this->Dismiss();
@ -132,6 +142,10 @@ void InputOverlay::OnInputEnterPressed(TextInput* input) {
this->Dismiss();
}
}
InputOverlay& InputOverlay::SetInputMode(IInput::InputMode mode) {
this->textInput->SetInputMode(mode);
return *this;
}
InputOverlay& InputOverlay::SetInputAcceptedCallback(InputAcceptedCallback cb) {
this->inputAcceptedCallback = cb;

View File

@ -55,6 +55,7 @@ namespace cursespp {
InputOverlay& SetText(const std::string& text);
InputOverlay& SetInputAcceptedCallback(InputAcceptedCallback cb);
InputOverlay& SetWidth(int width);
InputOverlay& SetInputMode(IInput::InputMode mode);
virtual void Layout();
virtual bool KeyPress(const std::string& key);
@ -62,6 +63,7 @@ namespace cursespp {
protected:
virtual void OnVisibilityChanged(bool visible);
virtual void OnInputEnterPressed(TextInput* input);
virtual void OnInputKeyPress(TextInput* input, std::string key);
private:
void Redraw();

View File

@ -164,7 +164,7 @@ void LayoutBase::Invalidate() {
bool LayoutBase::AddWindow(IWindowPtr window) {
if (!window) {
throw std::runtime_error("asdf");
throw std::runtime_error("window cannot be null!");
}
if (find(this->children, window) >= 0) {

View File

@ -49,6 +49,20 @@ namespace cursespp {
this->stack = stack;
}
virtual bool IsTop() {
if (LayoutBase::IsTop()) {
return true;
}
for (size_t i = 0; i < this->GetWindowCount(); i++) {
if (this->GetWindowAt(i)->IsTop()) {
return true;
}
}
return false;
}
protected:
OverlayStack* GetOverlayStack() {
return this->stack;

View File

@ -46,8 +46,10 @@ using namespace cursespp;
using namespace musik::core::runtime;
static int NEXT_ID = 0;
static bool drawPending = false;
static bool freeze = false;
static Window* top = nullptr;
static MessageQueue messageQueue;
@ -68,13 +70,16 @@ static inline void DrawCursor(IInput* input) {
}
}
void Window::WriteToScreen(IInput* input) {
bool Window::WriteToScreen(IInput* input) {
if (drawPending && !freeze) {
drawPending = false;
update_panels();
doupdate();
DrawCursor(input);
return true;
}
return false;
}
void Window::InvalidateScreen() {
@ -151,9 +156,15 @@ void Window::BringToTop() {
if (this->contentPanel != this->framePanel) {
top_panel(this->contentPanel);
}
::top = this;
}
}
bool Window::IsTop() {
return (::top == this);
}
void Window::SendToBottom() {
if (this->framePanel) {
bottom_panel(this->contentPanel);

View File

@ -105,12 +105,13 @@ namespace cursespp {
virtual bool IsVisible();
virtual bool IsFocused();
virtual bool IsTop();
virtual void OnParentVisibilityChanged(bool visible);
bool HasBadBounds() { return this->badBounds; }
static void WriteToScreen(IInput* input);
static bool WriteToScreen(IInput* input);
static void InvalidateScreen();
static void Freeze();
static void Unfreeze();