From 9b7a078348918ed3b277c671dd99dfb9a19b0cf3 Mon Sep 17 00:00:00 2001 From: Casey Langen Date: Wed, 25 Jan 2017 18:28:50 -0800 Subject: [PATCH] - Fixed some global focus (and focus styling issues) by introducing special color pairs for the focused state for both the frame and content views - Tweaked App.cpp to ensure newly focused windows have Focus() called, and previously focus windows have Blur() called. - More fixes to InputOverlay -- it's pretty much functional now. - Fixed bug in LayoutBase where child windows weren't properly getting their windows reset to null when the parent is destroyed. - Various other small fixes that were fallout from the focus cleanup. --- src/musikbox/app/layout/NowPlayingLayout.cpp | 2 + .../app/overlay/PlayQueueOverlays.cpp | 14 ++++ src/musikbox/app/overlay/PlayQueueOverlays.h | 4 ++ src/musikbox/cursespp/App.cpp | 15 +++- src/musikbox/cursespp/Colors.cpp | 1 + src/musikbox/cursespp/Colors.h | 3 + src/musikbox/cursespp/DialogOverlay.cpp | 5 +- src/musikbox/cursespp/IWindow.h | 6 ++ src/musikbox/cursespp/InputOverlay.cpp | 22 ++++++ src/musikbox/cursespp/InputOverlay.h | 5 +- src/musikbox/cursespp/LayoutBase.cpp | 38 ++++++----- src/musikbox/cursespp/ListOverlay.cpp | 11 +-- src/musikbox/cursespp/OverlayBase.h | 6 ++ src/musikbox/cursespp/ShortcutsWindow.cpp | 14 +--- src/musikbox/cursespp/ShortcutsWindow.h | 2 - src/musikbox/cursespp/Window.cpp | 68 ++++++++++--------- src/musikbox/cursespp/Window.h | 12 +++- 17 files changed, 147 insertions(+), 81 deletions(-) diff --git a/src/musikbox/app/layout/NowPlayingLayout.cpp b/src/musikbox/app/layout/NowPlayingLayout.cpp index a7374e38a..0e8fdf190 100755 --- a/src/musikbox/app/layout/NowPlayingLayout.cpp +++ b/src/musikbox/app/layout/NowPlayingLayout.cpp @@ -214,6 +214,8 @@ bool NowPlayingLayout::KeyPress(const std::string& key) { return true; } else if (key == "M-s") { + PlayQueueOverlays::ShowSavePlaylistOverlay(this->playback, this->library); + return true; } else if (ProcessEditOperation(key)) { return true; diff --git a/src/musikbox/app/overlay/PlayQueueOverlays.cpp b/src/musikbox/app/overlay/PlayQueueOverlays.cpp index 3c2c0f0d6..c6a460e32 100644 --- a/src/musikbox/app/overlay/PlayQueueOverlays.cpp +++ b/src/musikbox/app/overlay/PlayQueueOverlays.cpp @@ -47,6 +47,7 @@ #include #include #include +#include using namespace musik::core; using namespace musik::core::audio; @@ -198,3 +199,16 @@ void PlayQueueOverlays::ShowLoadPlaylistOverlay( cursespp::App::Overlays().Push(dialog); } + +void PlayQueueOverlays::ShowSavePlaylistOverlay( + musik::core::audio::PlaybackService& playback, + musik::core::ILibraryPtr library) +{ + std::shared_ptr dialog(new InputOverlay()); + + dialog->SetTitle("playlist name") + .SetWidth(36) + .SetText(""); + + cursespp::App::Overlays().Push(dialog); +} \ No newline at end of file diff --git a/src/musikbox/app/overlay/PlayQueueOverlays.h b/src/musikbox/app/overlay/PlayQueueOverlays.h index 1ee23e926..38eb657cf 100644 --- a/src/musikbox/app/overlay/PlayQueueOverlays.h +++ b/src/musikbox/app/overlay/PlayQueueOverlays.h @@ -61,6 +61,10 @@ namespace musik { musik::core::ILibraryPtr library, TrackListQueryCallback callback); + static void ShowSavePlaylistOverlay( + musik::core::audio::PlaybackService& playback, + musik::core::ILibraryPtr library); + private: PlayQueueOverlays(); }; diff --git a/src/musikbox/cursespp/App.cpp b/src/musikbox/cursespp/App.cpp index f97f62912..9ebd2f19a 100755 --- a/src/musikbox/cursespp/App.cpp +++ b/src/musikbox/cursespp/App.cpp @@ -260,16 +260,27 @@ void App::Run(ILayoutPtr layout) { void App::UpdateFocusedWindow(IWindowPtr window) { if (this->state.focused != window) { + if (this->state.focused) { + this->state.focused->Blur(); + } + this->state.focused = window; this->state.input = dynamic_cast(window.get()); this->state.keyHandler = dynamic_cast(window.get()); + + if (this->state.focused) { + this->state.focused->Focus(); + } } } void App::EnsureFocusIsValid() { ILayoutPtr layout = this->state.ActiveLayout(); - if (layout && layout->GetFocus() != this->state.focused) { - this->UpdateFocusedWindow(this->state.ActiveLayout()->GetFocus()); + if (layout) { + IWindowPtr focused = layout->GetFocus(); + if (focused != this->state.focused) { + this->UpdateFocusedWindow(focused); + } } } diff --git a/src/musikbox/cursespp/Colors.cpp b/src/musikbox/cursespp/Colors.cpp index 86178d554..8ba30d375 100755 --- a/src/musikbox/cursespp/Colors.cpp +++ b/src/musikbox/cursespp/Colors.cpp @@ -165,4 +165,5 @@ void Colors::Init(bool disableCustomColors) { init_pair(CURSESPP_OVERLAY_FRAME, blue, selected); init_pair(CURSESPP_OVERLAY_BACKGROUND, white, selected); + init_pair(CURSESPP_OVERLAY_INPUT_FRAME, red, selected); } diff --git a/src/musikbox/cursespp/Colors.h b/src/musikbox/cursespp/Colors.h index 370c4e007..84cf95700 100755 --- a/src/musikbox/cursespp/Colors.h +++ b/src/musikbox/cursespp/Colors.h @@ -36,6 +36,8 @@ #include "curses_config.h" +#define CURSESPP_DEFAULT_COLOR -1LL + #define CURSESPP_SELECTED_LIST_ITEM 1 #define CURSESPP_HIGHLIGHTED_LIST_ITEM 2 #define CURSESPP_HIGHLIGHTED_SELECTED_LIST_ITEM 3 @@ -63,6 +65,7 @@ #define CURSESPP_OVERLAY_FRAME 21 #define CURSESPP_OVERLAY_BACKGROUND 22 +#define CURSESPP_OVERLAY_INPUT_FRAME 23 namespace cursespp { class Colors { diff --git a/src/musikbox/cursespp/DialogOverlay.cpp b/src/musikbox/cursespp/DialogOverlay.cpp index 8d878e7ef..63db1e8c3 100644 --- a/src/musikbox/cursespp/DialogOverlay.cpp +++ b/src/musikbox/cursespp/DialogOverlay.cpp @@ -125,10 +125,7 @@ bool DialogOverlay::KeyPress(const std::string& key) { } if (this->autoDismiss) { - OverlayStack* overlays = this->GetOverlayStack(); - if (overlays) { - overlays->Remove(this); - } + this->Dismiss(); } return true; diff --git a/src/musikbox/cursespp/IWindow.h b/src/musikbox/cursespp/IWindow.h index 94a2d0fdc..3762fd528 100755 --- a/src/musikbox/cursespp/IWindow.h +++ b/src/musikbox/cursespp/IWindow.h @@ -56,6 +56,12 @@ namespace cursespp { virtual void Blur() = 0; virtual void SetContentColor(int64 color) = 0; virtual void SetFrameColor(int64 color) = 0; + virtual void SetFocusedFrameColor(int64 color) = 0; + virtual void SetFocusedContentColor(int64 color) = 0; + virtual int64 GetContentColor() = 0; + virtual int64 GetFrameColor() = 0; + virtual int64 GetFocusedContentColor() = 0; + virtual int64 GetFocusedFrameColor() = 0; virtual void SetFrameVisible(bool visible) = 0; virtual bool IsFrameVisible() = 0; virtual void SetSize(int width, int height) = 0; diff --git a/src/musikbox/cursespp/InputOverlay.cpp b/src/musikbox/cursespp/InputOverlay.cpp index 2837f7f84..1ebad6dd4 100644 --- a/src/musikbox/cursespp/InputOverlay.cpp +++ b/src/musikbox/cursespp/InputOverlay.cpp @@ -61,6 +61,9 @@ InputOverlay::InputOverlay() { this->textInput->SetFocusOrder(0); this->textInput->SetFrameColor(CURSESPP_OVERLAY_FRAME); this->textInput->SetContentColor(CURSESPP_OVERLAY_BACKGROUND); + this->textInput->SetFocusedFrameColor(CURSESPP_OVERLAY_INPUT_FRAME); + this->textInput->SetFocusedContentColor(CURSESPP_OVERLAY_BACKGROUND); + this->textInput->EnterPressed.connect(this, &InputOverlay::OnInputEnterPressed); this->AddWindow(this->textInput); } @@ -111,6 +114,25 @@ InputOverlay& InputOverlay::SetWidth(int width) { return *this; } +bool InputOverlay::KeyPress(const std::string& key) { + if (key == "^[") { /* esc closes */ + this->Dismiss(); + return true; + } + + return LayoutBase::KeyPress(key); +} + +void InputOverlay::OnInputEnterPressed(TextInput* input) { + if (input->GetText().size()) { + if (inputAcceptedCallback) { + inputAcceptedCallback(input->GetText()); + } + + this->Dismiss(); + } +} + InputOverlay& InputOverlay::SetInputAcceptedCallback(InputAcceptedCallback cb) { this->inputAcceptedCallback = cb; return *this; diff --git a/src/musikbox/cursespp/InputOverlay.h b/src/musikbox/cursespp/InputOverlay.h index d4fd4c93e..2e04b4bfc 100644 --- a/src/musikbox/cursespp/InputOverlay.h +++ b/src/musikbox/cursespp/InputOverlay.h @@ -39,7 +39,8 @@ namespace cursespp { class InputOverlay : - public OverlayBase + public OverlayBase, + public sigslot::has_slots<> #if (__clang_major__ == 7 && __clang_minor__ == 3) , public std::enable_shared_from_this #endif @@ -56,9 +57,11 @@ namespace cursespp { InputOverlay& SetWidth(int width); virtual void Layout(); + virtual bool KeyPress(const std::string& key); protected: virtual void OnVisibilityChanged(bool visible); + virtual void OnInputEnterPressed(TextInput* input); private: void Redraw(); diff --git a/src/musikbox/cursespp/LayoutBase.cpp b/src/musikbox/cursespp/LayoutBase.cpp index 750528f6f..99f28039d 100755 --- a/src/musikbox/cursespp/LayoutBase.cpp +++ b/src/musikbox/cursespp/LayoutBase.cpp @@ -67,12 +67,10 @@ bool sortByFocusOrder(IWindowPtr a, IWindowPtr b) { static inline IWindowPtr adjustFocus(IWindowPtr oldFocus, IWindowPtr newFocus) { if (oldFocus) { - oldFocus->SetFrameColor(CURSESPP_DEFAULT_FRAME_COLOR); oldFocus->Blur(); } if (newFocus) { - newFocus->SetFrameColor(CURSESPP_FOCUSED_FRAME_COLOR); newFocus->Focus(); } @@ -87,21 +85,23 @@ LayoutBase::LayoutBase(IWindow* parent) } LayoutBase::~LayoutBase() { - + for (IWindowPtr window : this->children) { + window->SetParent(nullptr); + } } void LayoutBase::OnVisibilityChanged(bool visible) { if (visible) { - for (size_t i = 0; i < this->children.size(); i++) { - this->children.at(i)->OnParentVisibilityChanged(true); + for (IWindowPtr window : this->children) { + window->OnParentVisibilityChanged(true); } this->IndexFocusables(); this->SortFocusables(); } else { - for (size_t i = 0; i < this->children.size(); i++) { - this->children.at(i)->OnParentVisibilityChanged(false); + for (IWindowPtr window : this->children) { + window->OnParentVisibilityChanged(false); } } } @@ -128,24 +128,24 @@ void LayoutBase::OnLayout() { void LayoutBase::OnParentVisibilityChanged(bool visible) { Window::OnParentVisibilityChanged(visible); - for (size_t i = 0; i < this->children.size(); i++) { - this->children.at(i)->OnParentVisibilityChanged(visible); + for (IWindowPtr window : this->children) { + window->OnParentVisibilityChanged(visible); } } void LayoutBase::BringToTop() { Window::BringToTop(); - for (size_t i = 0; i < this->children.size(); i++) { - this->children.at(i)->BringToTop(); + for (IWindowPtr window : this->children) { + window->BringToTop(); } this->Invalidate(); } void LayoutBase::SendToBottom() { - for (size_t i = 0; i < this->children.size(); i++) { - this->children.at(i)->SendToBottom(); + for (IWindowPtr window : this->children) { + window->SendToBottom(); } Window::SendToBottom(); @@ -157,12 +157,16 @@ void LayoutBase::Invalidate() { Window::Invalidate(); - for (size_t i = 0; i < this->children.size(); i++) { - this->children.at(i)->Invalidate(); + for (IWindowPtr window : this->children) { + window->Invalidate(); } } bool LayoutBase::AddWindow(IWindowPtr window) { + if (!window) { + throw std::runtime_error("asdf"); + } + if (find(this->children, window) >= 0) { return true; } @@ -206,8 +210,8 @@ void LayoutBase::IndexFocusables() { } this->focusable.clear(); - for (size_t i = 0; i < this->children.size(); i++) { - AddFocusable(this->children.at(i)); + for (IWindowPtr window : this->children) { + AddFocusable(window); } if (focusedWindow) { diff --git a/src/musikbox/cursespp/ListOverlay.cpp b/src/musikbox/cursespp/ListOverlay.cpp index d87473c6a..e43010044 100644 --- a/src/musikbox/cursespp/ListOverlay.cpp +++ b/src/musikbox/cursespp/ListOverlay.cpp @@ -44,12 +44,6 @@ using namespace cursespp; #define DEFAULT_WIDTH 26 #define MAX_HEIGHT 12 -#define DISMISS() \ - OverlayStack* overlays = this->GetOverlayStack(); \ - if (overlays) { \ - overlays->Remove(this); \ - } - ListOverlay::ListOverlay() { this->SetFrameVisible(true); this->SetFrameColor(CURSESPP_OVERLAY_FRAME); @@ -59,6 +53,7 @@ ListOverlay::ListOverlay() { this->listWindow.reset(new ListWindow()); this->listWindow->SetContentColor(CURSESPP_OVERLAY_BACKGROUND); + this->listWindow->SetFocusedContentColor(CURSESPP_OVERLAY_BACKGROUND); this->listWindow->SetFrameVisible(false); this->listWindow->SetFocusOrder(0); this->AddWindow(this->listWindow); @@ -131,7 +126,7 @@ ListOverlay& ListOverlay::SetDeleteKeyCallback(DeleteKeyCallback cb) { bool ListOverlay::KeyPress(const std::string& key) { if (key == "^[") { /* esc closes */ - DISMISS(); + this->Dismiss(); return true; } else if (key == "KEY_ENTER") { @@ -140,7 +135,7 @@ bool ListOverlay::KeyPress(const std::string& key) { this->adapter, listWindow->GetSelectedIndex()); } - DISMISS(); + this->Dismiss(); return true; } else if (key == "KEY_BACKSPACE" || key == "KEY_DC") { diff --git a/src/musikbox/cursespp/OverlayBase.h b/src/musikbox/cursespp/OverlayBase.h index f5e60e4d7..47f650298 100644 --- a/src/musikbox/cursespp/OverlayBase.h +++ b/src/musikbox/cursespp/OverlayBase.h @@ -54,6 +54,12 @@ namespace cursespp { return this->stack; } + void Dismiss() { + if (this->stack) { + stack->Remove(this); + } + } + private: OverlayStack* stack; }; diff --git a/src/musikbox/cursespp/ShortcutsWindow.cpp b/src/musikbox/cursespp/ShortcutsWindow.cpp index 21a37270e..ceca1f91c 100755 --- a/src/musikbox/cursespp/ShortcutsWindow.cpp +++ b/src/musikbox/cursespp/ShortcutsWindow.cpp @@ -44,7 +44,8 @@ ShortcutsWindow::ShortcutsWindow() : Window(nullptr) , alignment(text::AlignCenter) { this->SetFrameVisible(false); - this->UpdateContentColor(); + this->SetFocusedContentColor(CURSESPP_SHORTCUT_ROW_FOCUSED); + this->SetContentColor(CURSESPP_SHORTCUT_ROW_NORMAL); } ShortcutsWindow::~ShortcutsWindow() { @@ -76,17 +77,6 @@ void ShortcutsWindow::SetActive(const std::string& key) { this->Redraw(); } -void ShortcutsWindow::OnFocusChanged(bool focused) { - this->UpdateContentColor(); - this->Redraw(); -} - -void ShortcutsWindow::UpdateContentColor() { - this->SetContentColor(this->IsFocused() - ? CURSESPP_SHORTCUT_ROW_FOCUSED - : CURSESPP_SHORTCUT_ROW_NORMAL); -} - size_t ShortcutsWindow::CalculateLeftPadding() { if (this->alignment == text::AlignLeft) { return 0; diff --git a/src/musikbox/cursespp/ShortcutsWindow.h b/src/musikbox/cursespp/ShortcutsWindow.h index fcf987497..786f43c76 100755 --- a/src/musikbox/cursespp/ShortcutsWindow.h +++ b/src/musikbox/cursespp/ShortcutsWindow.h @@ -59,11 +59,9 @@ namespace cursespp { void SetActive(const std::string& key); protected: - virtual void OnFocusChanged(bool focused); virtual void OnRedraw(); private: - void UpdateContentColor(); size_t CalculateLeftPadding(); struct Entry { diff --git a/src/musikbox/cursespp/Window.cpp b/src/musikbox/cursespp/Window.cpp index eacc5e896..91d034c49 100755 --- a/src/musikbox/cursespp/Window.cpp +++ b/src/musikbox/cursespp/Window.cpp @@ -110,6 +110,8 @@ Window::Window(IWindow *parent) { this->y = 0; this->contentColor = CURSESPP_DEFAULT_CONTENT_COLOR; this->frameColor = CURSESPP_DEFAULT_FRAME_COLOR; + this->focusedContentColor = CURSESPP_DEFAULT_CONTENT_COLOR; + this->focusedFrameColor = CURSESPP_FOCUSED_FRAME_COLOR; this->drawFrame = true; this->isVisible = false; this->isFocused = false; @@ -188,10 +190,6 @@ void Window::SetParent(IWindow* parent) { if (this->parent != parent) { IWindowGroup* group = dynamic_cast(this->parent); - if (group) { - group->RemoveWindow(this->Window::shared_from_this()); - } - this->parent = parent; if (this->frame) { @@ -313,31 +311,37 @@ int Window::GetY() const { } void Window::SetContentColor(int64 color) { - this->contentColor = (color == -1 ? CURSESPP_DEFAULT_CONTENT_COLOR : color); + this->contentColor = (color == -1LL ? CURSESPP_DEFAULT_CONTENT_COLOR : color); + this->RepaintBackground(); +} - if (this->contentColor != -1 && this->content) { - wbkgd(this->frame, COLOR_PAIR(this->frameColor)); - - if (this->content != this->frame) { - wbkgd(this->content, COLOR_PAIR(this->contentColor)); - } - - this->Invalidate(); - } +void Window::SetFocusedContentColor(int64 color) { + this->focusedContentColor = (color == -1LL) ? CURSESPP_DEFAULT_CONTENT_COLOR : color; + this->RepaintBackground(); } void Window::SetFrameColor(int64 color) { - this->frameColor = (color == -1 ? CURSESPP_DEFAULT_FRAME_COLOR : color); + this->frameColor = (color == -1LL ? CURSESPP_DEFAULT_FRAME_COLOR : color); + this->RepaintBackground(); +} - if (this->drawFrame && this->frameColor != -1 && this->frame) { - wbkgd(this->frame, COLOR_PAIR(this->frameColor)); +void Window::SetFocusedFrameColor(int64 color) { + this->focusedFrameColor = (color == -1LL) ? CURSESPP_FOCUSED_FRAME_COLOR : color; + this->RepaintBackground(); +} - if (this->content != this->frame) { - wbkgd(this->content, COLOR_PAIR(this->contentColor)); - } - - this->Invalidate(); +void Window::RepaintBackground() { + if (this->drawFrame && this->frameColor != -1LL && this->frame && this->content != this->frame) { + wbkgd(this->frame, COLOR_PAIR(IsFocused() + ? this->focusedFrameColor : this->frameColor)); } + + if (this->content) { + wbkgd(this->content, COLOR_PAIR(IsFocused() + ? this->focusedContentColor : this->contentColor)); + } + + this->Invalidate(); } WINDOW* Window::GetContent() const { @@ -609,20 +613,16 @@ void Window::Clear() { werase(this->content); wmove(this->content, 0, 0); + bool focused = this->IsFocused(); + int64 contentColor = isFocused ? this->focusedContentColor : this->contentColor; + int64 frameColor = isFocused ? this->focusedFrameColor : this->frameColor; + if (this->content == this->frame) { - if (this->contentColor != -1) { - wbkgd(this->frame, COLOR_PAIR(this->contentColor)); - } - else { - wbkgd(this->frame, COLOR_PAIR(this->frameColor)); - } + wbkgd(this->frame, COLOR_PAIR(contentColor)); } else { - wbkgd(this->frame, COLOR_PAIR(this->frameColor)); - - if (this->content != this->frame) { - wbkgd(this->content, COLOR_PAIR(this->contentColor)); - } + wbkgd(this->frame, COLOR_PAIR(frameColor)); + wbkgd(this->content, COLOR_PAIR(contentColor)); } } @@ -639,6 +639,7 @@ void Window::Focus() { this->isFocused = true; this->isDirty = true; this->OnFocusChanged(true); + this->RepaintBackground(); this->Redraw(); } } @@ -648,6 +649,7 @@ void Window::Blur() { this->isFocused = false; this->isDirty = true; this->OnFocusChanged(false); + this->RepaintBackground(); this->Redraw(); } } diff --git a/src/musikbox/cursespp/Window.h b/src/musikbox/cursespp/Window.h index 251ca09ff..f0fbebc18 100755 --- a/src/musikbox/cursespp/Window.h +++ b/src/musikbox/cursespp/Window.h @@ -70,6 +70,14 @@ namespace cursespp { virtual void SetContentColor(int64 color); virtual void SetFrameColor(int64 color); + virtual void SetFocusedContentColor(int64 color); + virtual void SetFocusedFrameColor(int64 color); + + virtual int64 GetContentColor() { return this->contentColor; } + virtual int64 GetFrameColor() { return this->frameColor; } + virtual int64 GetFocusedContentColor() { return this->focusedContentColor; } + virtual int64 GetFocusedFrameColor() { return this->focusedFrameColor; } + virtual void SetSize(int width, int height); virtual void SetPosition(int x, int y); virtual void MoveAndResize(int x, int y, int width, int height); @@ -120,11 +128,10 @@ namespace cursespp { void Destroy(); void Recreate(); void Clear(); + void RepaintBackground(); void RecreateForUpdatedDimensions(); bool CheckForBoundsError(); - int64 GetContentColor() { return this->contentColor; } - int64 GetFrameColor() { return this->frameColor; } virtual void OnDimensionsChanged(); virtual void OnVisibilityChanged(bool visible); @@ -143,6 +150,7 @@ namespace cursespp { int focusOrder; int id; int64 contentColor, frameColor; + int64 focusedContentColor, focusedFrameColor; int width, height, x, y; }; }