mirror of
https://github.com/clangen/musikcube.git
synced 2025-03-14 04:18:36 +00:00
Basic mouse handling support!
This commit is contained in:
parent
f9d57c06b4
commit
9048467e45
78
src/3rdparty/win32_src/pdcurses/pdcscrn.c
vendored
78
src/3rdparty/win32_src/pdcurses/pdcscrn.c
vendored
@ -1959,6 +1959,7 @@ static LRESULT ALIGN_STACK CALLBACK WndProc (const HWND hwnd,
|
||||
{
|
||||
int button_down = -1, button_up = -1;
|
||||
static int mouse_buttons_pressed = 0;
|
||||
static int mouse_click_type = -1;
|
||||
static LPARAM mouse_lParam;
|
||||
static uint64_t last_click_time[PDC_MAX_MOUSE_BUTTONS];
|
||||
/* in millisec since 1970 */
|
||||
@ -2128,9 +2129,15 @@ static LRESULT ALIGN_STACK CALLBACK WndProc (const HWND hwnd,
|
||||
BUTTON4_PRESSED, BUTTON5_PRESSED };
|
||||
|
||||
modified_key_to_return = 0;
|
||||
if( SP && (SP->_trap_mbe & remap_table[wParam]))
|
||||
set_mouse( (const int) wParam, BUTTON_PRESSED, mouse_lParam);
|
||||
if (SP && (SP->_trap_mbe & remap_table[wParam]))
|
||||
{
|
||||
if ( mouse_click_type != -1)
|
||||
{
|
||||
set_mouse( (const int)wParam, mouse_click_type, mouse_lParam);
|
||||
}
|
||||
}
|
||||
KillTimer( PDC_hWnd, (int)wParam);
|
||||
mouse_click_type = -1;
|
||||
mouse_buttons_pressed ^= (1 << wParam);
|
||||
}
|
||||
else if( SP && curscr && curscr->_y)
|
||||
@ -2195,27 +2202,35 @@ static LRESULT ALIGN_STACK CALLBACK WndProc (const HWND hwnd,
|
||||
if( button_down >= 0)
|
||||
{
|
||||
modified_key_to_return = 0;
|
||||
SetTimer( hwnd, button_down, SP->mouse_wait, NULL);
|
||||
mouse_buttons_pressed |= (1 << button_down);
|
||||
mouse_lParam = lParam;
|
||||
}
|
||||
if( button_up >= 0)
|
||||
{
|
||||
int message_to_send = -1;
|
||||
static const int single_remap_table[PDC_MAX_MOUSE_BUTTONS] =
|
||||
{ BUTTON1_CLICKED, BUTTON2_CLICKED, BUTTON3_CLICKED,
|
||||
BUTTON4_CLICKED, BUTTON5_CLICKED };
|
||||
|
||||
static const int double_remap_table[PDC_MAX_MOUSE_BUTTONS] =
|
||||
{ BUTTON1_DOUBLE_CLICKED, BUTTON2_DOUBLE_CLICKED,
|
||||
BUTTON3_DOUBLE_CLICKED, BUTTON4_DOUBLE_CLICKED,
|
||||
BUTTON5_DOUBLE_CLICKED };
|
||||
|
||||
static const int triple_remap_table[PDC_MAX_MOUSE_BUTTONS] =
|
||||
{ BUTTON1_TRIPLE_CLICKED, BUTTON2_TRIPLE_CLICKED,
|
||||
BUTTON3_TRIPLE_CLICKED, BUTTON4_TRIPLE_CLICKED,
|
||||
BUTTON5_TRIPLE_CLICKED };
|
||||
|
||||
static const int released_remap_table[PDC_MAX_MOUSE_BUTTONS] =
|
||||
{ BUTTON1_RELEASED, BUTTON2_RELEASED, BUTTON3_RELEASED,
|
||||
BUTTON4_RELEASED, BUTTON5_RELEASED };
|
||||
|
||||
modified_key_to_return = 0;
|
||||
if( (mouse_buttons_pressed >> button_up) & 1)
|
||||
{
|
||||
const uint64_t curr_click_time =
|
||||
milliseconds_since_1970( );
|
||||
static const int double_remap_table[PDC_MAX_MOUSE_BUTTONS] =
|
||||
{ BUTTON1_DOUBLE_CLICKED, BUTTON2_DOUBLE_CLICKED,
|
||||
BUTTON3_DOUBLE_CLICKED, BUTTON4_DOUBLE_CLICKED,
|
||||
BUTTON5_DOUBLE_CLICKED };
|
||||
static const int triple_remap_table[PDC_MAX_MOUSE_BUTTONS] =
|
||||
{ BUTTON1_TRIPLE_CLICKED, BUTTON2_TRIPLE_CLICKED,
|
||||
BUTTON3_TRIPLE_CLICKED, BUTTON4_TRIPLE_CLICKED,
|
||||
BUTTON5_TRIPLE_CLICKED };
|
||||
|
||||
static int n_previous_clicks;
|
||||
|
||||
if( curr_click_time <
|
||||
@ -2224,36 +2239,27 @@ static LRESULT ALIGN_STACK CALLBACK WndProc (const HWND hwnd,
|
||||
else /* zero for a "normal" click, 1 */
|
||||
n_previous_clicks = 0; /* for a dblclick, 2 for a triple */
|
||||
|
||||
if( n_previous_clicks >= 2 &&
|
||||
(SP->_trap_mbe & triple_remap_table[button_up]))
|
||||
message_to_send = BUTTON_TRIPLE_CLICKED;
|
||||
else if( n_previous_clicks >= 1 &&
|
||||
(SP->_trap_mbe & double_remap_table[button_up]))
|
||||
message_to_send = BUTTON_DOUBLE_CLICKED;
|
||||
else /* either it's not a doubleclick, or we aren't */
|
||||
{ /* checking for double clicks */
|
||||
static const int remap_table[PDC_MAX_MOUSE_BUTTONS] =
|
||||
{ BUTTON1_CLICKED, BUTTON2_CLICKED, BUTTON3_CLICKED,
|
||||
BUTTON4_CLICKED, BUTTON5_CLICKED };
|
||||
if (n_previous_clicks >= 2 &&
|
||||
(SP->_trap_mbe & triple_remap_table[button_up]))
|
||||
mouse_click_type = BUTTON_TRIPLE_CLICKED;
|
||||
else if (n_previous_clicks >= 1 &&
|
||||
(SP->_trap_mbe & double_remap_table[button_up]))
|
||||
mouse_click_type = BUTTON_DOUBLE_CLICKED;
|
||||
else if (SP->_trap_mbe & single_remap_table[button_up])
|
||||
/* either it's not a doubleclick, or we aren't */
|
||||
/* checking for double clicks */
|
||||
mouse_click_type = BUTTON_CLICKED;
|
||||
else
|
||||
mouse_click_type = -1;
|
||||
|
||||
if( SP->_trap_mbe & remap_table[button_up])
|
||||
message_to_send = BUTTON_CLICKED;
|
||||
}
|
||||
KillTimer( hwnd, button_up);
|
||||
SetTimer( hwnd, button_up, SP->mouse_wait, NULL);
|
||||
mouse_buttons_pressed ^= (1 << button_up);
|
||||
last_click_time[button_up] = curr_click_time;
|
||||
}
|
||||
if( message_to_send == -1) /* might just send as a 'released' msg */
|
||||
{
|
||||
static const int remap_table[PDC_MAX_MOUSE_BUTTONS] =
|
||||
{ BUTTON1_RELEASED, BUTTON2_RELEASED, BUTTON3_RELEASED,
|
||||
BUTTON4_RELEASED, BUTTON5_RELEASED };
|
||||
|
||||
if( SP->_trap_mbe & remap_table[button_up])
|
||||
message_to_send = BUTTON_RELEASED;
|
||||
}
|
||||
if( message_to_send != -1)
|
||||
set_mouse( button_up, message_to_send, lParam);
|
||||
if( SP->_trap_mbe & released_remap_table[button_up])
|
||||
set_mouse(button_up, BUTTON_RELEASED, lParam);
|
||||
}
|
||||
|
||||
return DefWindowProc( hwnd, message, wParam, lParam) ;
|
||||
|
@ -39,20 +39,20 @@
|
||||
|
||||
namespace musik { namespace core {
|
||||
|
||||
extern std::string GetHomeDirectory();
|
||||
extern std::string GetApplicationDirectory();
|
||||
extern std::string GetDataDirectory(bool create = true);
|
||||
extern std::string GetPath(const std::string &sFile);
|
||||
extern std::string GetPluginDirectory();
|
||||
extern std::string NormalizeDir(std::string path);
|
||||
extern void OpenFile(const std::string& path);
|
||||
extern int64_t Checksum(char *data,unsigned int bytes);
|
||||
extern size_t CopyString(const std::string& src, char* dst, size_t size);
|
||||
extern void ReplaceAll(std::string& input, const std::string& find, const std::string& replace);
|
||||
extern bool FileToByteArray(const std::string& path, char** target, int& size, bool nullTerminate = false);
|
||||
std::string GetHomeDirectory();
|
||||
std::string GetApplicationDirectory();
|
||||
std::string GetDataDirectory(bool create = true);
|
||||
std::string GetPath(const std::string &sFile);
|
||||
std::string GetPluginDirectory();
|
||||
std::string NormalizeDir(std::string path);
|
||||
void OpenFile(const std::string& path);
|
||||
int64_t Checksum(char *data,unsigned int bytes);
|
||||
size_t CopyString(const std::string& src, char* dst, size_t size);
|
||||
void ReplaceAll(std::string& input, const std::string& find, const std::string& replace);
|
||||
bool FileToByteArray(const std::string& path, char** target, int& size, bool nullTerminate = false);
|
||||
|
||||
/* renames ~/.mC2 -> ~/.musikcube */
|
||||
extern void MigrateOldDataDirectory();
|
||||
extern void RemoveOldDlls();
|
||||
/* file-migration stuff. */
|
||||
void MigrateOldDataDirectory(); /* renames ~/.mC2 -> ~/.musikcube */
|
||||
void RemoveOldDlls();
|
||||
|
||||
} }
|
||||
|
@ -178,7 +178,7 @@ namespace musik { namespace core { namespace lastfm {
|
||||
});
|
||||
}
|
||||
|
||||
const std::string CreateLinkUrl(const std::string& token) {
|
||||
const std::string CreateAccountLinkUrl(const std::string& token) {
|
||||
return ACCOUNT_LINK_URL_BASE + token;
|
||||
}
|
||||
|
||||
|
@ -45,12 +45,12 @@ namespace musik { namespace core { namespace lastfm {
|
||||
using TokenCallback = std::function<void(std::string)>;
|
||||
using SessionCallback = std::function<void(Session)>;
|
||||
|
||||
extern void CreateAccountLinkToken(TokenCallback callback);
|
||||
extern const std::string CreateLinkUrl(const std::string& token);
|
||||
extern void CreateSession(const std::string& token, SessionCallback session);
|
||||
extern void Scrobble(musik::core::TrackPtr track);
|
||||
void CreateAccountLinkToken(TokenCallback callback);
|
||||
const std::string CreateAccountLinkUrl(const std::string& token);
|
||||
void CreateSession(const std::string& token, SessionCallback session);
|
||||
void Scrobble(musik::core::TrackPtr track);
|
||||
|
||||
extern Session LoadSession();
|
||||
extern void SaveSession(const Session& session);
|
||||
extern void ClearSession();
|
||||
Session LoadSession();
|
||||
void SaveSession(const Session& session);
|
||||
void ClearSession();
|
||||
} } }
|
@ -35,6 +35,7 @@ set (CUBE_SRCS
|
||||
./cursespp/Colors.cpp
|
||||
./cursespp/DialogOverlay.cpp
|
||||
./cursespp/InputOverlay.cpp
|
||||
./cursespp/IMouseHandler.cpp
|
||||
./cursespp/LayoutBase.cpp
|
||||
./cursespp/ListOverlay.cpp
|
||||
./cursespp/ListWindow.cpp
|
||||
|
@ -60,6 +60,14 @@ namespace components = musik::core::prefs::components;
|
||||
x == this->artists || \
|
||||
x == this->genres
|
||||
|
||||
#define CREATE_CATEGORY(view, title, type, order) \
|
||||
view.reset(new CategoryListView(playback, this->library, type)); \
|
||||
view->EntryActivated.connect(this, &CategorySearchLayout::OnCategoryEntryActivated); \
|
||||
view->SetFrameTitle(title); \
|
||||
view->SetAllowArrowKeyPropagation(); \
|
||||
this->AddWindow(view); \
|
||||
view->SetFocusOrder(order);
|
||||
|
||||
CategorySearchLayout::CategorySearchLayout(musik::core::audio::PlaybackService& playback, ILibraryPtr library)
|
||||
: LayoutBase() {
|
||||
this->library = library;
|
||||
@ -101,13 +109,6 @@ void CategorySearchLayout::OnLayout() {
|
||||
this->genres->MoveAndResize(categoryWidth * 2, categoryY, lastCategoryWidth, categoryHeight);
|
||||
}
|
||||
|
||||
#define CREATE_CATEGORY(view, title, type, order) \
|
||||
view.reset(new CategoryListView(playback, this->library, type)); \
|
||||
view->SetFrameTitle(title); \
|
||||
view->SetAllowArrowKeyPropagation(); \
|
||||
this->AddWindow(view); \
|
||||
view->SetFocusOrder(order);
|
||||
|
||||
void CategorySearchLayout::InitializeWindows(musik::core::audio::PlaybackService& playback) {
|
||||
this->input.reset(new cursespp::TextInput());
|
||||
this->input->TextChanged.connect(this, &CategorySearchLayout::OnInputChanged);
|
||||
@ -158,23 +159,22 @@ void CategorySearchLayout::OnVisibilityChanged(bool visible) {
|
||||
}
|
||||
}
|
||||
|
||||
void CategorySearchLayout::OnCategoryEntryActivated(
|
||||
cursespp::ListWindow* listWindow, size_t index)
|
||||
{
|
||||
CategoryListView* category =
|
||||
static_cast<CategoryListView*>(listWindow);
|
||||
|
||||
if ((int) index >= 0) {
|
||||
this->SearchResultSelected(
|
||||
this,
|
||||
category->GetFieldName(),
|
||||
category->GetSelectedId());
|
||||
}
|
||||
}
|
||||
|
||||
bool CategorySearchLayout::KeyPress(const std::string& key) {
|
||||
IWindowPtr focus = this->GetFocus();
|
||||
CategoryListView* category = dynamic_cast<CategoryListView*>(focus.get());
|
||||
|
||||
if (category) {
|
||||
if (key == "KEY_ENTER") {
|
||||
int index = (int) category->GetSelectedIndex();
|
||||
if (index >= 0) {
|
||||
this->SearchResultSelected(
|
||||
this,
|
||||
category->GetFieldName(),
|
||||
category->GetSelectedId());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (Hotkeys::Is(Hotkeys::Down, key)) {
|
||||
if (this->GetFocus() == this->input) {
|
||||
|
@ -78,6 +78,7 @@ namespace musik {
|
||||
|
||||
private:
|
||||
void InitializeWindows(musik::core::audio::PlaybackService& playback);
|
||||
void OnCategoryEntryActivated(cursespp::ListWindow* sender, size_t index);
|
||||
void Requery();
|
||||
void SaveSession();
|
||||
|
||||
|
@ -128,7 +128,7 @@ void LastFmOverlay::UpdateMessage() {
|
||||
|
||||
case State::WaitingForUser:
|
||||
case State::RegisterError: {
|
||||
std::string url = lastfm::CreateLinkUrl(this->linkToken);
|
||||
std::string url = lastfm::CreateAccountLinkUrl(this->linkToken);
|
||||
core::ReplaceAll(message, "{{link}}", url);
|
||||
break;
|
||||
}
|
||||
@ -180,7 +180,7 @@ void LastFmOverlay::UpdateButtons() {
|
||||
this->AddButton(
|
||||
"o", "o", "open url",
|
||||
[this](std::string key) {
|
||||
core::OpenFile(lastfm::CreateLinkUrl(this->linkToken));
|
||||
core::OpenFile(lastfm::CreateAccountLinkUrl(this->linkToken));
|
||||
});
|
||||
|
||||
|
||||
|
@ -152,6 +152,10 @@ void ServerOverlay::InitViews() {
|
||||
this->shortcuts->AddShortcut("ESC", _TSTR("button_cancel"));
|
||||
this->shortcuts->AddShortcut("M-s", _TSTR("button_save"));
|
||||
|
||||
this->shortcuts->SetChangedCallback([this](std::string key) {
|
||||
this->KeyPress(key);
|
||||
});
|
||||
|
||||
/* web socket server */
|
||||
this->enableWssCb.reset(new Checkbox());
|
||||
this->enableWssCb->SetText(_TSTR("settings_server_enable_websockets"));
|
||||
@ -323,7 +327,7 @@ bool ServerOverlay::Save() {
|
||||
}
|
||||
|
||||
bool ServerOverlay::KeyPress(const std::string& key) {
|
||||
if (key == "^[") { /* esc closes */
|
||||
if (key == "^[" || key == "ESC") { /* esc closes */
|
||||
this->Dismiss();
|
||||
return true;
|
||||
}
|
||||
|
@ -212,22 +212,23 @@ void TrackListView::ProcessMessage(IMessage &message) {
|
||||
}
|
||||
}
|
||||
|
||||
void TrackListView::OnEntryActivated(size_t index) {
|
||||
if (headers.HeaderAt(this->GetSelectedIndex())) {
|
||||
TrackPtr track = this->GetSelectedTrack();
|
||||
PlayQueueOverlays::ShowAlbumDividerOverlay(
|
||||
MessageQueue(), this->playback, this->library, track);
|
||||
}
|
||||
else {
|
||||
playback::Play(*this, this->playback);
|
||||
}
|
||||
|
||||
ListWindow::OnEntryActivated(index);
|
||||
}
|
||||
|
||||
bool TrackListView::KeyPress(const std::string& key) {
|
||||
bool handled = false;
|
||||
|
||||
if (key == "KEY_ENTER") {
|
||||
if (headers.HeaderAt(this->GetSelectedIndex())) {
|
||||
TrackPtr track = this->GetSelectedTrack();
|
||||
PlayQueueOverlays::ShowAlbumDividerOverlay(
|
||||
MessageQueue(), this->playback, this->library, track);
|
||||
}
|
||||
else {
|
||||
playback::Play(*this, this->playback);
|
||||
}
|
||||
|
||||
handled = true;
|
||||
}
|
||||
else if (Hotkeys::Is(Hotkeys::ContextMenu, key)) {
|
||||
if (Hotkeys::Is(Hotkeys::ContextMenu, key)) {
|
||||
TrackPtr track = this->GetSelectedTrack();
|
||||
if (!headers.HeaderAt(this->GetSelectedIndex())) {
|
||||
if (track) {
|
||||
|
@ -97,6 +97,8 @@ namespace musik {
|
||||
|
||||
protected:
|
||||
virtual cursespp::IScrollAdapter& GetScrollAdapter();
|
||||
virtual void OnEntryActivated(size_t index);
|
||||
|
||||
void OnQueryCompleted(musik::core::db::IQuery* query);
|
||||
|
||||
/* this view has headers and track entry types */
|
||||
@ -151,6 +153,7 @@ namespace musik {
|
||||
};
|
||||
|
||||
void OnTrackChanged(size_t index, musik::core::TrackPtr track);
|
||||
|
||||
void ScrollToPlaying();
|
||||
void SelectFirstTrack();
|
||||
|
||||
|
@ -88,6 +88,7 @@ App::App(const std::string& title) {
|
||||
|
||||
this->quit = false;
|
||||
this->minWidth = this->minHeight = 0;
|
||||
this->mouseEnabled = true;
|
||||
|
||||
#ifdef WIN32
|
||||
this->iconId = 0;
|
||||
@ -111,6 +112,7 @@ App::App(const std::string& title) {
|
||||
keypad(stdscr, TRUE);
|
||||
refresh();
|
||||
curs_set(0);
|
||||
mousemask(ALL_MOUSE_EVENTS, nullptr);
|
||||
|
||||
#ifndef WIN32
|
||||
set_escdelay(20);
|
||||
@ -228,6 +230,10 @@ void App::Quit() {
|
||||
this->quit = true;
|
||||
}
|
||||
|
||||
void App::SetMouseEnabled(bool enabled) {
|
||||
this->mouseEnabled = enabled;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
bool App::Running(const std::string& uniqueId) {
|
||||
return App::Running(uniqueId, uniqueId);
|
||||
@ -258,6 +264,7 @@ void App::Run(ILayoutPtr layout) {
|
||||
Colors::SetTheme(this->colorTheme);
|
||||
}
|
||||
|
||||
MEVENT mouseEvent;
|
||||
int64_t ch;
|
||||
std::string kn;
|
||||
|
||||
@ -312,6 +319,21 @@ process:
|
||||
else if (kn == "KEY_RESIZE") {
|
||||
resizeAt = App::Now() + REDRAW_DEBOUNCE_MS;
|
||||
}
|
||||
else if (this->mouseEnabled && kn == "KEY_MOUSE") {
|
||||
#ifdef WIN32
|
||||
if (nc_getmouse(&mouseEvent) == 0) {
|
||||
#else
|
||||
if (getmouse(&mouseEvent) == 0) {
|
||||
#endif
|
||||
auto active = this->state.ActiveLayout();
|
||||
if (active) {
|
||||
using Event = IMouseHandler::Event;
|
||||
auto window = dynamic_cast<IWindow*>(active.get());
|
||||
Event event(mouseEvent, window);
|
||||
active->MouseEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* order: focused input, global key handler, then layout. */
|
||||
else if (!this->state.input ||
|
||||
!this->state.focused->IsVisible() ||
|
||||
|
@ -60,6 +60,7 @@ namespace cursespp {
|
||||
void SetColorMode(Colors::Mode mode);
|
||||
void SetColorTheme(const std::string& fn);
|
||||
void SetMinimumSize(int width, int height);
|
||||
void SetMouseEnabled(bool enabled);
|
||||
bool IsOverlayVisible() { return this->state.overlay != nullptr; }
|
||||
void SetMinimizeToTray(bool minimizeToTray);
|
||||
void Minimize();
|
||||
@ -123,6 +124,7 @@ namespace cursespp {
|
||||
Colors::Mode colorMode;
|
||||
std::string colorTheme;
|
||||
int minWidth, minHeight;
|
||||
bool mouseEnabled;
|
||||
bool quit;
|
||||
|
||||
#ifdef WIN32
|
||||
|
@ -105,3 +105,12 @@ bool Checkbox::KeyPress(const std::string& key) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Checkbox::MouseEvent(const IMouseHandler::Event& event) {
|
||||
if (event.Button1Clicked()) {
|
||||
this->FocusInParent();
|
||||
this->SetChecked(!this->checked);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
@ -59,6 +59,7 @@ namespace cursespp {
|
||||
virtual std::string GetText() { return this->buffer; }
|
||||
virtual bool IsChecked() { return this->checked; }
|
||||
virtual bool KeyPress(const std::string& key);
|
||||
virtual bool MouseEvent(const IMouseHandler::Event& event);
|
||||
virtual void OnRedraw();
|
||||
|
||||
private:
|
||||
|
@ -53,6 +53,11 @@ DialogOverlay::DialogOverlay() {
|
||||
|
||||
this->shortcuts.reset(new ShortcutsWindow());
|
||||
this->shortcuts->SetAlignment(text::AlignRight);
|
||||
|
||||
this->shortcuts->SetChangedCallback([this](std::string key) {
|
||||
this->ProcessKey(key);
|
||||
});
|
||||
|
||||
this->LayoutBase::AddWindow(this->shortcuts);
|
||||
}
|
||||
|
||||
@ -116,7 +121,8 @@ DialogOverlay& DialogOverlay::AddButton(
|
||||
ButtonCallback callback)
|
||||
{
|
||||
this->shortcuts->AddShortcut(key, caption);
|
||||
this->buttons[rawKey] = callback;
|
||||
this->buttons[rawKey] = callback; /* for KeyPress() */
|
||||
this->buttons[key] = callback; /* for ShortcutsWindow::ChangedCallback */
|
||||
this->Layout();
|
||||
this->Invalidate();
|
||||
return *this;
|
||||
@ -127,7 +133,7 @@ DialogOverlay& DialogOverlay::OnDismiss(DismissCallback dismissCb) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool DialogOverlay::KeyPress(const std::string& key) {
|
||||
bool DialogOverlay::ProcessKey(const std::string& key) {
|
||||
auto it = this->buttons.find(key);
|
||||
|
||||
if (it != this->buttons.end()) {
|
||||
@ -144,6 +150,13 @@ bool DialogOverlay::KeyPress(const std::string& key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DialogOverlay::KeyPress(const std::string& key) {
|
||||
if (this->ProcessKey(key)) {
|
||||
return true;
|
||||
}
|
||||
return LayoutBase::KeyPress(key);
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,7 @@ namespace cursespp {
|
||||
private:
|
||||
void Redraw();
|
||||
void RecalculateSize();
|
||||
bool ProcessKey(const std::string& key);
|
||||
|
||||
std::string title;
|
||||
std::string message;
|
||||
|
@ -37,10 +37,17 @@
|
||||
#include "IWindowGroup.h"
|
||||
#include "IDisplayable.h"
|
||||
#include "IKeyHandler.h"
|
||||
#include "IMouseHandler.h"
|
||||
#include <memory>
|
||||
|
||||
namespace cursespp {
|
||||
class ILayout : public IWindowGroup, public IKeyHandler, public IOrderable, public IDisplayable {
|
||||
class ILayout:
|
||||
public IWindowGroup,
|
||||
public IKeyHandler,
|
||||
public IMouseHandler,
|
||||
public IOrderable,
|
||||
public IDisplayable
|
||||
{
|
||||
public:
|
||||
enum FocusMode {
|
||||
FocusModeCircular = 0,
|
||||
|
73
src/musikcube/cursespp/IMouseHandler.cpp
Normal file
73
src/musikcube/cursespp/IMouseHandler.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <stdafx.h>
|
||||
#include "IMouseHandler.h"
|
||||
#include "IWindow.h"
|
||||
|
||||
using namespace cursespp;
|
||||
|
||||
IMouseHandler::Event::Event(const Event& original, int childX, int childY) {
|
||||
x = original.x - childX;
|
||||
y = original.y - childY;
|
||||
state = original.state;
|
||||
}
|
||||
|
||||
IMouseHandler::Event::Event(const Event& original, IWindow* parent) {
|
||||
if (parent) {
|
||||
int frameOffset = parent->IsFrameVisible() ? 1 : 0;
|
||||
x = original.x - parent->GetX() - frameOffset;
|
||||
y = original.y - parent->GetY() - frameOffset;
|
||||
}
|
||||
else {
|
||||
x = original.x;
|
||||
y = original.y;
|
||||
}
|
||||
state = original.state;
|
||||
}
|
||||
|
||||
IMouseHandler::Event::Event(const MEVENT& original, IWindow* parent) {
|
||||
if (parent) {
|
||||
int frameOffset = parent->IsFrameVisible() ? 1 : 0;
|
||||
x = original.x - parent->GetX() - frameOffset;
|
||||
y = original.y - parent->GetY() - frameOffset;
|
||||
}
|
||||
else {
|
||||
x = original.x;
|
||||
y = original.y;
|
||||
}
|
||||
state = original.bstate;
|
||||
}
|
65
src/musikcube/cursespp/IMouseHandler.h
Normal file
65
src/musikcube/cursespp/IMouseHandler.h
Normal file
@ -0,0 +1,65 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 <stdafx.h>
|
||||
#include "curses_config.h"
|
||||
|
||||
namespace cursespp {
|
||||
class IWindow;
|
||||
|
||||
class IMouseHandler {
|
||||
public:
|
||||
struct Event {
|
||||
Event(const Event& original, int childX, int childY);
|
||||
Event(const Event& original, IWindow* parent = nullptr);
|
||||
Event(const MEVENT& original, IWindow* parent = nullptr);
|
||||
|
||||
bool Button1Clicked() const { return state & BUTTON1_CLICKED; }
|
||||
bool Button2Clicked() const { return state & BUTTON2_CLICKED; }
|
||||
bool Button3Clicked() const { return state & BUTTON3_CLICKED; }
|
||||
|
||||
bool Button1DoubleClicked() const { return state & BUTTON1_DOUBLE_CLICKED; }
|
||||
bool Button2DoubleClicked() const { return state & BUTTON2_DOUBLE_CLICKED; }
|
||||
bool Button3DoubleClicked() const { return state & BUTTON3_DOUBLE_CLICKED; }
|
||||
|
||||
int x, y;
|
||||
mmask_t state;
|
||||
};
|
||||
|
||||
virtual ~IMouseHandler() { }
|
||||
virtual bool MouseEvent(const Event& mouseEvent) = 0;
|
||||
};
|
||||
}
|
@ -37,6 +37,7 @@
|
||||
#include "curses_config.h"
|
||||
#include "IDisplayable.h"
|
||||
#include "IOrderable.h"
|
||||
#include "IMouseHandler.h"
|
||||
|
||||
#include <core/runtime/IMessage.h>
|
||||
#include <core/runtime/IMessageTarget.h>
|
||||
@ -45,6 +46,7 @@ namespace cursespp {
|
||||
class IWindow :
|
||||
public IOrderable,
|
||||
public IDisplayable,
|
||||
public IMouseHandler,
|
||||
public musik::core::runtime::IMessageTarget
|
||||
{
|
||||
public:
|
||||
|
@ -403,5 +403,23 @@ bool LayoutBase::KeyPress(const std::string& key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LayoutBase::MouseEvent(const IMouseHandler::Event& mouseEvent) {
|
||||
for (auto window : this->children) {
|
||||
auto x = window->GetX();
|
||||
auto y = window->GetY();
|
||||
auto cx = window->GetWidth();
|
||||
auto cy = window->GetHeight();
|
||||
if (mouseEvent.x >= x && mouseEvent.x < x + cx &&
|
||||
mouseEvent.y >= y && mouseEvent.y < y + cy)
|
||||
{
|
||||
auto relative = IMouseHandler::Event(mouseEvent, window.get());
|
||||
if (window->MouseEvent(relative)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
@ -95,6 +95,9 @@ namespace cursespp {
|
||||
/* IKeyHandler */
|
||||
virtual bool KeyPress(const std::string& key);
|
||||
|
||||
/* IMouseHandler */
|
||||
virtual bool MouseEvent(const IMouseHandler::Event& mouseEvent);
|
||||
|
||||
/* IWindowGroup */
|
||||
virtual bool AddWindow(IWindowPtr window);
|
||||
virtual bool RemoveWindow(IWindowPtr window);
|
||||
|
@ -287,6 +287,42 @@ void ListWindow::OnDimensionsChanged() {
|
||||
this->ScrollTo(this->GetScrollPosition().firstVisibleEntryIndex);
|
||||
}
|
||||
|
||||
bool ListWindow::KeyPress(const std::string& key) {
|
||||
if (key == "KEY_ENTER") {
|
||||
auto selected = this->GetSelectedIndex();
|
||||
if (selected != NO_SELECTION) {
|
||||
this->OnEntryActivated(selected);
|
||||
}
|
||||
}
|
||||
return ScrollableWindow::KeyPress(key);
|
||||
}
|
||||
|
||||
bool ListWindow::MouseEvent(const IMouseHandler::Event& event) {
|
||||
bool result = ScrollableWindow::MouseEvent(event);
|
||||
|
||||
auto first = this->scrollPosition.firstVisibleEntryIndex;
|
||||
|
||||
if (first == NO_SELECTION) {
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t offset = first + (size_t) event.y;
|
||||
|
||||
if (event.Button1Clicked()) {
|
||||
this->SetSelectedIndex(offset);
|
||||
}
|
||||
else if (event.Button1DoubleClicked()) {
|
||||
this->SetSelectedIndex(offset);
|
||||
this->OnEntryActivated(offset); /* internal */
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ListWindow::OnEntryActivated(size_t index) {
|
||||
this->EntryActivated(this, index); /* external */
|
||||
}
|
||||
|
||||
IScrollAdapter::ScrollPosition& ListWindow::GetMutableScrollPosition() {
|
||||
this->scrollPosition.logicalIndex = this->GetSelectedIndex(); /* hack */
|
||||
return this->scrollPosition;
|
||||
|
@ -51,6 +51,7 @@ namespace cursespp {
|
||||
|
||||
sigslot::signal3<ListWindow*, size_t, size_t> SelectionChanged;
|
||||
sigslot::signal2<ListWindow*, size_t> Invalidated;
|
||||
sigslot::signal2<ListWindow*, size_t> EntryActivated;
|
||||
|
||||
ListWindow(std::shared_ptr<IScrollAdapter> adapter, IWindow *parent = nullptr);
|
||||
ListWindow(IWindow *parent = nullptr);
|
||||
@ -73,10 +74,14 @@ namespace cursespp {
|
||||
|
||||
virtual const IScrollAdapter::ScrollPosition& GetScrollPosition();
|
||||
|
||||
virtual bool KeyPress(const std::string& key);
|
||||
virtual bool MouseEvent(const IMouseHandler::Event& event);
|
||||
|
||||
void SetScrollbarVisible(bool visible);
|
||||
|
||||
protected:
|
||||
virtual void OnSelectionChanged(size_t newIndex, size_t oldIndex);
|
||||
virtual void OnEntryActivated(size_t index);
|
||||
virtual void OnInvalidated();
|
||||
virtual void OnDimensionsChanged();
|
||||
virtual void DecorateFrame();
|
||||
|
@ -142,6 +142,15 @@ bool ScrollableWindow::KeyPress(const std::string& key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScrollableWindow::MouseEvent(const IMouseHandler::Event& event) {
|
||||
if (event.Button1Clicked()) {
|
||||
this->FocusInParent();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void ScrollableWindow::OnRedraw() {
|
||||
IScrollAdapter *adapter = &GetScrollAdapter();
|
||||
ScrollPos &pos = this->GetMutableScrollPosition();
|
||||
|
@ -64,6 +64,7 @@ namespace cursespp {
|
||||
virtual void OnDimensionsChanged();
|
||||
|
||||
virtual bool KeyPress(const std::string& key);
|
||||
virtual bool MouseEvent(const IMouseHandler::Event& event);
|
||||
|
||||
virtual void ScrollToTop();
|
||||
virtual void ScrollToBottom();
|
||||
|
@ -147,6 +147,28 @@ bool ShortcutsWindow::KeyPress(const std::string& key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ShortcutsWindow::MouseEvent(const IMouseHandler::Event& mouseEvent) {
|
||||
if (mouseEvent.Button1Clicked()) {
|
||||
for (auto entry : this->entries) {
|
||||
auto& pos = entry->position;
|
||||
if (mouseEvent.x >= pos.offset &&
|
||||
mouseEvent.x < pos.offset + pos.width)
|
||||
{
|
||||
this->activeKey = entry->key;
|
||||
|
||||
this->Redraw();
|
||||
|
||||
if (this->changedCallback) {
|
||||
this->changedCallback(this->activeKey);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ShortcutsWindow::OnFocusChanged(bool focused) {
|
||||
if (focused) {
|
||||
this->originalKey = this->activeKey;
|
||||
@ -180,6 +202,7 @@ void ShortcutsWindow::OnRedraw() {
|
||||
size_t leftPadding = this->CalculateLeftPadding();
|
||||
wmove(c, 0, leftPadding);
|
||||
|
||||
size_t currentX = leftPadding;
|
||||
size_t remaining = this->GetContentWidth();
|
||||
for (size_t i = 0; i < this->entries.size() && remaining > 0; i++) {
|
||||
auto e = this->entries[i];
|
||||
@ -197,6 +220,14 @@ void ShortcutsWindow::OnRedraw() {
|
||||
std::string key = " " + e->key + " ";
|
||||
std::string value = " " + e->description + " ";
|
||||
|
||||
/* calculate the offset and width, this is used for mouse
|
||||
click handling! */
|
||||
size_t width = u8cols(key + value);
|
||||
e->position.offset = currentX;
|
||||
e->position.width = width;
|
||||
currentX += 1 + width; /* 1 is the extra leading space */
|
||||
|
||||
/* draw the shortcut key */
|
||||
size_t len = u8cols(key);
|
||||
if (len > remaining) {
|
||||
key = text::Ellipsize(key, remaining);
|
||||
@ -213,6 +244,7 @@ void ShortcutsWindow::OnRedraw() {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* draw the description */
|
||||
len = u8cols(value);
|
||||
if (len > remaining) {
|
||||
value = text::Ellipsize(value, remaining);
|
||||
@ -220,7 +252,6 @@ void ShortcutsWindow::OnRedraw() {
|
||||
}
|
||||
|
||||
checked_wprintw(c, value.c_str());
|
||||
|
||||
remaining -= len;
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ namespace cursespp {
|
||||
void SetActive(const std::string& key);
|
||||
|
||||
virtual bool KeyPress(const std::string& key) override;
|
||||
virtual bool MouseEvent(const IMouseHandler::Event& mouseEvent) override;
|
||||
|
||||
protected:
|
||||
virtual void OnRedraw() override;
|
||||
@ -74,6 +75,10 @@ namespace cursespp {
|
||||
size_t CalculateLeftPadding();
|
||||
int getActiveIndex();
|
||||
|
||||
struct Position {
|
||||
int offset{ 0 }, width{ 0 };
|
||||
};
|
||||
|
||||
struct Entry {
|
||||
Entry(const std::string& key, const std::string& desc, int64_t attrs = -1) {
|
||||
this->key = key;
|
||||
@ -81,6 +86,7 @@ namespace cursespp {
|
||||
this->attrs = attrs;
|
||||
}
|
||||
|
||||
Position position;
|
||||
std::string key;
|
||||
std::string description;
|
||||
int64_t attrs;
|
||||
|
@ -259,4 +259,13 @@ void TextInput::SetText(const std::string& value) {
|
||||
void TextInput::SetHint(const std::string& hint) {
|
||||
this->hintText = hint;
|
||||
this->Redraw();
|
||||
}
|
||||
|
||||
bool TextInput::MouseEvent(const IMouseHandler::Event& event) {
|
||||
if (event.Button1Clicked()) {
|
||||
this->position = std::max(0, std::min((int)this->bufferLength, event.x));
|
||||
this->FocusInParent();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
@ -72,6 +72,7 @@ namespace cursespp {
|
||||
virtual InputMode GetInputMode() { return this->inputMode; }
|
||||
|
||||
virtual bool KeyPress(const std::string& key);
|
||||
virtual bool MouseEvent(const IMouseHandler::Event& event);
|
||||
|
||||
virtual void SetText(const std::string& value);
|
||||
virtual std::string GetText() { return this->buffer; }
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <cursespp/Screen.h>
|
||||
#include <cursespp/Colors.h>
|
||||
#include <cursespp/Text.h>
|
||||
#include <cursespp/ILayout.h>
|
||||
|
||||
#include "TextLabel.h"
|
||||
|
||||
@ -116,4 +117,13 @@ bool TextLabel::KeyPress(const std::string& key) {
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool TextLabel::MouseEvent(const IMouseHandler::Event& event) {
|
||||
if (event.Button1Clicked()) {
|
||||
this->FocusInParent();
|
||||
this->Activated(this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ namespace cursespp {
|
||||
virtual void OnRedraw();
|
||||
|
||||
virtual bool KeyPress(const std::string& key);
|
||||
virtual bool MouseEvent(const IMouseHandler::Event& event);
|
||||
|
||||
private:
|
||||
std::string buffer;
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "Window.h"
|
||||
#include "IWindowGroup.h"
|
||||
#include "IInput.h"
|
||||
#include "ILayout.h"
|
||||
#include "Colors.h"
|
||||
#include "Screen.h"
|
||||
#include "Text.h"
|
||||
@ -822,6 +823,18 @@ void Window::SetNavigationKeys(std::shared_ptr<INavigationKeys> keys) {
|
||||
::keys = keys;
|
||||
}
|
||||
|
||||
bool Window::MouseEvent(const IMouseHandler::Event& mouseEvent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Window::FocusInParent() {
|
||||
auto layout = dynamic_cast<ILayout*>(this->GetParent());
|
||||
if (layout) {
|
||||
return layout->SetFocus(shared_from_this());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* default keys for navigating around sub-views. apps can override this shim to
|
||||
provide VIM-like keybindings, if it wants... */
|
||||
static class DefaultNavigationKeys : public INavigationKeys {
|
||||
|
@ -119,6 +119,8 @@ namespace cursespp {
|
||||
|
||||
bool HasBadBounds() { return this->badBounds; }
|
||||
|
||||
bool MouseEvent(const IMouseHandler::Event& mouseEvent);
|
||||
|
||||
static bool WriteToScreen(IInput* input);
|
||||
static void InvalidateScreen();
|
||||
static void Freeze();
|
||||
@ -134,11 +136,14 @@ namespace cursespp {
|
||||
void PostMessage(int messageType, int64_t user1 = 0, int64_t user2 = 0, int64_t delay = 0);
|
||||
void DebounceMessage(int messageType, int64_t user1 = 0, int64_t user2 = 0, int64_t delay = 0);
|
||||
void RemoveMessage(int messageType);
|
||||
bool FocusInParent();
|
||||
|
||||
static INavigationKeys& NavigationKeys();
|
||||
|
||||
virtual void Create();
|
||||
virtual void Destroy();
|
||||
virtual void DecorateFrame();
|
||||
|
||||
void Recreate();
|
||||
void Clear();
|
||||
void DrawFrameAndTitle();
|
||||
|
@ -177,6 +177,7 @@ xcopy "$(SolutionDir)src\3rdparty\bin\win32\font\*.ttf" "$(TargetDir)fonts\" /Y
|
||||
<ClCompile Include="cursespp\Checkbox.cpp" />
|
||||
<ClCompile Include="cursespp\Colors.cpp" />
|
||||
<ClCompile Include="cursespp\DialogOverlay.cpp" />
|
||||
<ClCompile Include="cursespp\IMouseHandler.cpp" />
|
||||
<ClCompile Include="cursespp\InputOverlay.cpp" />
|
||||
<ClCompile Include="cursespp\LayoutBase.cpp" />
|
||||
<ClCompile Include="cursespp\ListOverlay.cpp" />
|
||||
@ -243,6 +244,7 @@ xcopy "$(SolutionDir)src\3rdparty\bin\win32\font\*.ttf" "$(TargetDir)fonts\" /Y
|
||||
<ClInclude Include="cursespp\IInput.h" />
|
||||
<ClInclude Include="cursespp\IKeyHandler.h" />
|
||||
<ClInclude Include="cursespp\ILayout.h" />
|
||||
<ClInclude Include="cursespp\IMouseHandler.h" />
|
||||
<ClInclude Include="cursespp\INavigationKeys.h" />
|
||||
<ClInclude Include="cursespp\InputOverlay.h" />
|
||||
<ClInclude Include="cursespp\IOrderable.h" />
|
||||
|
@ -159,6 +159,9 @@
|
||||
<ClCompile Include="app\overlay\LastFmOverlay.cpp">
|
||||
<Filter>app\overlay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cursespp\IMouseHandler.cpp">
|
||||
<Filter>cursespp</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
@ -367,6 +370,9 @@
|
||||
<ClInclude Include="app\overlay\LastFmOverlay.h">
|
||||
<Filter>app\overlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="cursespp\IMouseHandler.h">
|
||||
<Filter>cursespp</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="cursespp">
|
||||
|
Loading…
x
Reference in New Issue
Block a user