Migrated MainLayout to use new cursespp AppLayout.

This commit is contained in:
casey langen 2018-12-20 21:41:58 -08:00
parent 160262dd7a
commit f732a87f3d
8 changed files with 33 additions and 305 deletions

View File

@ -35,6 +35,7 @@ set (CUBE_SRCS
./app/window/TrackListView.cpp
./app/window/TransportWindow.cpp
./cursespp/App.cpp
./cursespp/AppLayout.cpp
./cursespp/Checkbox.cpp
./cursespp/Colors.cpp
./cursespp/DialogOverlay.cpp

View File

@ -39,6 +39,7 @@
#include <cursespp/TextInput.h>
#include <cursespp/ShortcutsWindow.h>
#include <cursespp/ScrollableWindow.h>
#include <cursespp/ITopLevelLayout.h>
#include <app/window/LogWindow.h>
#include <app/window/TransportWindow.h>
@ -47,8 +48,6 @@
#include <core/audio/ITransport.h>
#include "ITopLevelLayout.h"
namespace musik {
namespace cube {
class ConsoleLayout :
@ -56,7 +55,7 @@ namespace musik {
#if (__clang_major__ == 7 && __clang_minor__ == 3)
public std::enable_shared_from_this<ConsoleLayout>,
#endif
public ITopLevelLayout,
public cursespp::ITopLevelLayout,
public sigslot::has_slots<>
{
public:

View File

@ -37,10 +37,9 @@
#include <cursespp/LayoutBase.h>
#include <cursespp/ListWindow.h>
#include <cursespp/ShortcutsWindow.h>
#include <cursespp/ITopLevelLayout.h>
#include <vector>
#include "ITopLevelLayout.h"
namespace musik {
namespace cube {
class HotkeysLayout :
@ -48,7 +47,7 @@ namespace musik {
#if (__clang_major__ == 7 && __clang_minor__ == 3)
public std::enable_shared_from_this<HotkeysLayout>,
#endif
public ITopLevelLayout,
public cursespp::ITopLevelLayout,
public sigslot::has_slots<>
{
public:

View File

@ -1,49 +0,0 @@
//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2007-2017 musikcube team
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of the author nor the names of other contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include <cursespp/ShortcutsWindow.h>
namespace musik {
namespace cube {
class ITopLevelLayout {
public:
virtual ~ITopLevelLayout() { }
virtual void SetShortcutsWindow(
cursespp::ShortcutsWindow* w) = 0;
};
}
}

View File

@ -36,7 +36,7 @@
#include <cursespp/LayoutBase.h>
#include <cursespp/ShortcutsWindow.h>
#include <cursespp/ITopLevelLayout.h>
#include <app/layout/BrowseLayout.h>
#include <app/layout/DirectoryLayout.h>
#include <app/layout/NowPlayingLayout.h>
@ -49,13 +49,11 @@
#include <sigslot/sigslot.h>
#include "ITopLevelLayout.h"
namespace musik {
namespace cube {
class LibraryLayout :
public cursespp::LayoutBase,
public ITopLevelLayout,
public cursespp::ITopLevelLayout,
public sigslot::has_slots<>
{
public:

View File

@ -60,23 +60,6 @@ using namespace musik::core::runtime;
using namespace cursespp;
static UpdateCheck updateCheck;
static std::map<ILayout*, int> lastFocusMap;
#define ENABLE_DEMO_MODE 0
#if ENABLE_DEMO_MODE
static std::string lastKey;
static int lastKeyRepeat = 0;
#endif
static int last(ILayout* layout) {
auto it = lastFocusMap.find(layout);
return (it == lastFocusMap.end()) ? 0 : it->second;
}
static void last(ILayout* layout, int last) {
lastFocusMap[layout] = last;
}
static void updateSyncingText(TextLabel* label, int updates) {
try {
@ -100,12 +83,9 @@ MainLayout::MainLayout(
musik::core::audio::PlaybackService& playback,
ILibraryPtr library)
: shortcutsFocused(false)
, topLevelLayout(nullptr)
, syncUpdateCount(0)
, library(library)
, LayoutBase() {
this->Initialize();
, AppLayout(app) {
this->prefs = Preferences::ForComponent("settings");
library->Indexer()->Started.connect(this, &MainLayout::OnIndexerStarted);
@ -117,13 +97,17 @@ MainLayout::MainLayout(
this->settingsLayout = std::make_shared<SettingsLayout>(app, library, playback);
this->hotkeysLayout = std::make_shared<HotkeysLayout>();
this->syncing.reset(new TextLabel());
this->syncing->SetContentColor(Color::Banner);
this->syncing->Hide();
this->AddWindow(this->syncing);
/* take user to settings if they don't have a valid configuration. otherwise,
switch to the library view immediately */
std::vector<std::string> paths;
library->Indexer()->GetPaths(paths);
this->SetMainLayout(paths.size() > 0 ? libraryLayout : settingsLayout);
this->SetLayout(paths.size() > 0 ? libraryLayout : settingsLayout);
this->EnableDemoModeIfNecessary();
this->RunUpdateCheck();
}
@ -132,18 +116,9 @@ MainLayout::~MainLayout() {
}
void MainLayout::OnLayout() {
size_t cx = Screen::GetWidth(), cy = Screen::GetHeight();
#if ENABLE_DEMO_MODE
this->hotkey->MoveAndResize(0, cy - 1, cx, 1);
--cy;
#endif
int yOffset = 0;
auto state = this->library->Indexer()->GetState();
if (state == IIndexer::StateIndexing) {
yOffset = 1;
if (this->library->Indexer()->GetState() == IIndexer::StateIndexing) {
size_t cx = this->GetContentWidth();
this->SetPadding(1, 0, 0, 0);
this->syncing->MoveAndResize(0, 0, cx, 1);
this->syncing->Show();
@ -152,180 +127,33 @@ void MainLayout::OnLayout() {
}
}
else {
this->SetPadding(0, 0, 0, 0);
this->syncing->Hide();
}
if (this->layout) {
this->layout->MoveAndResize(0, yOffset, cx, cy - 1 - yOffset);
this->layout->Show();
this->layout->BringToTop();
if (this->shortcutsFocused) {
this->layout->SetFocus(IWindowPtr());
}
}
this->shortcuts->MoveAndResize(0, cy - 1, cx, 1);
}
void MainLayout::Initialize() {
this->shortcuts.reset(new ShortcutsWindow());
this->AddWindow(this->shortcuts);
#if ENABLE_DEMO_MODE
this->hotkey.reset(new TextLabel());
this->hotkey->SetContentColor(Color::Footer);
this->hotkey->SetText("keypress: <none>", text::AlignCenter);
this->AddWindow(this->hotkey);
#endif
this->syncing.reset(new TextLabel());
this->syncing->SetContentColor(Color::Banner);
this->syncing->Hide();
this->AddWindow(this->syncing);
}
cursespp::IWindowPtr MainLayout::GetFocus() {
if (this->shortcutsFocused) {
return this->shortcuts;
}
if (this->layout) {
return this->layout->GetFocus();
}
return cursespp::IWindowPtr();
}
IWindowPtr MainLayout::FocusNext() {
return (this->shortcutsFocused)
? this->BlurShortcuts() : this->layout->FocusNext();
}
IWindowPtr MainLayout::FocusPrev() {
return (this->shortcutsFocused)
? this->BlurShortcuts() : this->layout->FocusPrev();
}
void MainLayout::SetMainLayout(std::shared_ptr<cursespp::LayoutBase> layout) {
if (layout != this->layout) {
if (this->layout) {
if (this->lastFocus) {
this->layout->SetFocus(this->lastFocus);
}
this->RemoveWindow(this->layout);
last(this->layout.get(), this->layout->GetFocusIndex());
this->layout->SetFocusIndex(-1);
this->layout->Hide();
}
this->lastFocus.reset();
if (this->topLevelLayout) {
this->topLevelLayout->SetShortcutsWindow(nullptr);
}
this->layout = layout;
this->shortcuts->RemoveAll();
if (this->layout) {
this->topLevelLayout = dynamic_cast<ITopLevelLayout*>(layout.get());
if (this->topLevelLayout) {
this->topLevelLayout->SetShortcutsWindow(this->shortcuts.get());
}
this->AddWindow(this->layout);
this->layout->SetFocusOrder(0);
this->layout->SetFocusIndex(last(this->layout.get()));
this->Layout();
}
}
}
cursespp::IWindowPtr MainLayout::BlurShortcuts() {
this->shortcuts->Blur();
this->shortcutsFocused = false;
if (this->layout) {
bool refocused = false;
if (this->lastFocus) {
refocused = this->layout->SetFocus(this->lastFocus);
this->lastFocus.reset();
}
if (!refocused) {
this->layout->FocusNext();
}
}
return this->layout ? this->layout->GetFocus() : IWindowPtr();
}
void MainLayout::FocusShortcuts() {
this->shortcuts->Focus();
if (this->layout) {
this->lastFocus = this->layout->GetFocus();
if (this->lastFocus) {
this->lastFocus->Blur();
}
this->layout->SetFocus(IWindowPtr());
}
this->shortcuts->Focus();
AppLayout::OnLayout();
}
bool MainLayout::KeyPress(const std::string& key) {
/* deal with top-level view switching first. */
if (Hotkeys::Is(Hotkeys::NavigateConsole, key)) {
this->SetMainLayout(consoleLayout);
this->SetLayout(consoleLayout);
return true;
}
else if (Hotkeys::Is(Hotkeys::NavigateHotkeys, key)) {
this->SetMainLayout(hotkeysLayout);
this->SetLayout(hotkeysLayout);
return true;
}
else if (Hotkeys::Is(Hotkeys::NavigateLibrary, key)) {
this->SetMainLayout(libraryLayout);
this->SetLayout(libraryLayout);
return true;
}
else if (Hotkeys::Is(Hotkeys::NavigateSettings, key)) {
this->SetMainLayout(settingsLayout);
this->SetLayout(settingsLayout);
return true;
}
/* otherwise, see if the user is monkeying around with the
shortcut bar focus... */
if (key == "^[" ||
(key == "KEY_ENTER" && this->shortcutsFocused) ||
(Hotkeys::Is(Hotkeys::Up, key) && this->shortcutsFocused))
{
this->shortcutsFocused = !this->shortcutsFocused;
if (this->shortcutsFocused) {
this->FocusShortcuts();
}
else {
this->BlurShortcuts();
}
return true;
}
if (this->shortcutsFocused) {
if (Hotkeys::Is(Hotkeys::Down, key) || Hotkeys::Is(Hotkeys::Left, key) ||
Hotkeys::Is(Hotkeys::Up, key) || Hotkeys::Is(Hotkeys::Right, key))
{
/* layouts allow focusing via TAB and sometimes arrow
keys. suppress these from bubbling. */
return true;
}
}
/* otherwise, pass along to our child layout */
return this->layout ? this->layout->KeyPress(key) : false;
return AppLayout::KeyPress(key);
}
void MainLayout::Start() {
@ -346,16 +174,16 @@ void MainLayout::ProcessMessage(musik::core::runtime::IMessage &message) {
int type = message.Type();
if (type == message::JumpToConsole) {
this->SetMainLayout(consoleLayout);
this->SetLayout(consoleLayout);
}
else if (type == message::JumpToSettings) {
this->SetMainLayout(settingsLayout);
this->SetLayout(settingsLayout);
}
else if (type == message::JumpToHotkeys) {
this->SetMainLayout(hotkeysLayout);
this->SetLayout(hotkeysLayout);
}
else if (type == message::JumpToLibrary) {
this->SetMainLayout(libraryLayout);
this->SetLayout(libraryLayout);
}
if (type == message::IndexerStarted) {
this->syncUpdateCount = 0;
@ -396,32 +224,4 @@ void MainLayout::RunUpdateCheck() {
UpdateCheck::ShowUpgradeAvailableOverlay(version, url);
}
});
}
void MainLayout::EnableDemoModeIfNecessary() {
#if ENABLE_DEMO_MODE
App::Instance().SetKeyHook([this](const std::string& key) -> bool {
static std::map<std::string, std::string> SANITIZE = {
{ "^I", "TAB" }, { " ", "SPACE" }, { "^[", "ESC" }
};
auto it = SANITIZE.find(key);
std::string normalized = (it == SANITIZE.end()) ? key : it->second;
if (normalized == lastKey) {
++lastKeyRepeat;
if (lastKeyRepeat >= 2) {
normalized = normalized + " (x" + std::to_string(lastKeyRepeat) + ")";
}
}
else {
lastKey = normalized;
lastKeyRepeat = 1;
}
std::string keypress = "keypress: " + (normalized.size() ? normalized : "<none>");
this->hotkey->SetText(keypress, text::AlignCenter);
return false;
});
#endif
}

View File

@ -35,10 +35,9 @@
#pragma once
#include <cursespp/App.h>
#include <cursespp/LayoutBase.h>
#include <cursespp/AppLayout.h>
#include <cursespp/TextInput.h>
#include <cursespp/TextLabel.h>
#include <cursespp/ShortcutsWindow.h>
#include <core/audio/PlaybackService.h>
#include <core/support/Preferences.h>
@ -47,18 +46,15 @@
#include <core/audio/MasterTransport.h>
#include "ITopLevelLayout.h"
#include <sigslot/sigslot.h>
namespace musik {
namespace cube {
class MainLayout :
public cursespp::LayoutBase,
public cursespp::AppLayout
#if (__clang_major__ == 7 && __clang_minor__ == 3)
public std::enable_shared_from_this<MainLayout>,
public std::enable_shared_from_this<MainLayout>
#endif
public sigslot::has_slots<>
{
public:
MainLayout(
@ -73,13 +69,8 @@ namespace musik {
virtual bool KeyPress(const std::string& key) override;
virtual void OnLayout() override;
virtual cursespp::IWindowPtr GetFocus() override;
virtual cursespp::IWindowPtr FocusNext() override;
virtual cursespp::IWindowPtr FocusPrev() override;
virtual void ProcessMessage(musik::core::runtime::IMessage &message) override;
void SetMainLayout(std::shared_ptr<cursespp::LayoutBase> layout);
private:
void OnIndexerStarted();
void OnIndexerProgress(int count);
@ -88,23 +79,13 @@ namespace musik {
void Initialize();
void RunUpdateCheck();
void EnableDemoModeIfNecessary();
cursespp::IWindowPtr BlurShortcuts();
void FocusShortcuts();
std::shared_ptr<musik::core::Preferences> prefs;
std::shared_ptr<cursespp::ShortcutsWindow> shortcuts;
std::shared_ptr<cursespp::LayoutBase> layout;
std::shared_ptr<cursespp::TextLabel> syncing;
std::shared_ptr<cursespp::LayoutBase> consoleLayout;
std::shared_ptr<cursespp::LayoutBase> libraryLayout;
std::shared_ptr<cursespp::LayoutBase> settingsLayout;
std::shared_ptr<cursespp::LayoutBase> hotkeysLayout;
std::shared_ptr<cursespp::TextLabel> hotkey;
musik::core::ILibraryPtr library;
cursespp::IWindowPtr lastFocus;
ITopLevelLayout* topLevelLayout;
bool shortcutsFocused;
int syncUpdateCount;
};

View File

@ -44,6 +44,7 @@
#include <cursespp/TextLabel.h>
#include <cursespp/TextInput.h>
#include <cursespp/DialogOverlay.h>
#include <cursespp/ITopLevelLayout.h>
#include <core/audio/PlaybackService.h>
#include <core/audio/MasterTransport.h>
@ -56,12 +57,10 @@
#include <sigslot/sigslot.h>
#include "ITopLevelLayout.h"
namespace musik {
namespace cube {
class SettingsLayout :
public ITopLevelLayout,
public cursespp::ITopLevelLayout,
public cursespp::LayoutBase,
#if (__clang_major__ == 7 && __clang_minor__ == 3)
public std::enable_shared_from_this<SettingsLayout>,