- 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.
This commit is contained in:
Casey Langen 2017-01-25 18:28:50 -08:00
parent 545d179873
commit 9b7a078348
17 changed files with 147 additions and 81 deletions

View File

@ -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;

View File

@ -47,6 +47,7 @@
#include <cursespp/SimpleScrollAdapter.h>
#include <cursespp/ListOverlay.h>
#include <cursespp/DialogOverlay.h>
#include <cursespp/InputOverlay.h>
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<InputOverlay> dialog(new InputOverlay());
dialog->SetTitle("playlist name")
.SetWidth(36)
.SetText("");
cursespp::App::Overlays().Push(dialog);
}

View File

@ -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();
};

View File

@ -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<IInput*>(window.get());
this->state.keyHandler = dynamic_cast<IKeyHandler*>(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);
}
}
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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<InputOverlay>
#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();

View File

@ -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) {

View File

@ -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") {

View File

@ -54,6 +54,12 @@ namespace cursespp {
return this->stack;
}
void Dismiss() {
if (this->stack) {
stack->Remove(this);
}
}
private:
OverlayStack* stack;
};

View File

@ -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;

View File

@ -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 {

View File

@ -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<IWindowGroup*>(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();
}
}

View File

@ -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;
};
}