mirror of
https://github.com/clangen/musikcube.git
synced 2025-02-06 12:39:54 +00:00
Added scrollbar support to ListOverlay.
This commit is contained in:
parent
cfdd4db53d
commit
bcec9dc7ca
@ -42,6 +42,7 @@ set (CUBE_SRCS
|
||||
./cursespp/Screen.cpp
|
||||
./cursespp/ScrollableWindow.cpp
|
||||
./cursespp/ScrollAdapterBase.cpp
|
||||
./cursespp/Scrollbar.cpp
|
||||
./cursespp/SimpleScrollAdapter.cpp
|
||||
./cursespp/SingleLineEntry.cpp
|
||||
./cursespp/Text.cpp
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include <stdafx.h>
|
||||
#include "ListOverlay.h"
|
||||
#include "Scrollbar.h"
|
||||
#include "Colors.h"
|
||||
#include "Screen.h"
|
||||
#include "Text.h"
|
||||
@ -43,6 +44,40 @@ using namespace cursespp;
|
||||
#define VERTICAL_PADDING 2
|
||||
#define DEFAULT_WIDTH 26
|
||||
|
||||
/* a little custom type that allows us to draw a scrollbar
|
||||
ourself, outside of the list window frame. */
|
||||
class ListOverlay::CustomListWindow : public ListWindow {
|
||||
public:
|
||||
using Callback = std::function<void()>;
|
||||
|
||||
CustomListWindow(Callback decorator, Callback adapterChanged)
|
||||
: ListWindow() {
|
||||
this->decorator = decorator;
|
||||
this->adapterChanged = adapterChanged;
|
||||
}
|
||||
|
||||
virtual void OnAdapterChanged() {
|
||||
if (adapterChanged) { adapterChanged(); };
|
||||
ListWindow::OnAdapterChanged();
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
decorator = adapterChanged = Callback();
|
||||
}
|
||||
|
||||
size_t EntryCount() {
|
||||
return this->GetScrollAdapter().GetEntryCount();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void DecorateFrame() {
|
||||
if (decorator) { decorator(); }
|
||||
}
|
||||
|
||||
private:
|
||||
Callback decorator, adapterChanged;
|
||||
};
|
||||
|
||||
ListOverlay::ListOverlay() {
|
||||
this->SetFrameVisible(true);
|
||||
this->SetFrameColor(CURSESPP_OVERLAY_FRAME);
|
||||
@ -53,7 +88,20 @@ ListOverlay::ListOverlay() {
|
||||
this->width = this->height = 0;
|
||||
this->setWidth = this->setWidthPercent = 0;
|
||||
|
||||
this->listWindow.reset(new ListWindow());
|
||||
auto decorator = [this] {
|
||||
if (this->ScrollbarVisible()) {
|
||||
Scrollbar::Draw(this->listWindow.get(), this->scrollbar.get());
|
||||
}
|
||||
};
|
||||
|
||||
auto adapterChanged = [this] { this->Layout(); };
|
||||
|
||||
this->scrollbar.reset(new Window());
|
||||
this->scrollbar->SetFrameVisible(false);
|
||||
this->scrollbar->SetContentColor(CURSESPP_OVERLAY_CONTENT);
|
||||
this->AddWindow(this->scrollbar);
|
||||
|
||||
this->listWindow.reset(new CustomListWindow(decorator, adapterChanged));
|
||||
this->listWindow->SetContentColor(CURSESPP_OVERLAY_CONTENT);
|
||||
this->listWindow->SetFocusedContentColor(CURSESPP_OVERLAY_CONTENT);
|
||||
this->listWindow->SetFrameVisible(false);
|
||||
@ -62,6 +110,7 @@ ListOverlay::ListOverlay() {
|
||||
}
|
||||
|
||||
ListOverlay::~ListOverlay() {
|
||||
this->listWindow->Reset();
|
||||
}
|
||||
|
||||
void ListOverlay::Layout() {
|
||||
@ -74,21 +123,41 @@ void ListOverlay::Layout() {
|
||||
this->width,
|
||||
this->height);
|
||||
|
||||
this->listWindow->MoveAndResize(
|
||||
1, /* one pixel padding L and R */
|
||||
2, /* below the title, plus an extra space */
|
||||
this->GetContentWidth() - 2,
|
||||
this->height - 4); /* top and bottom padding + title */
|
||||
bool scrollbar = this->ScrollbarVisible();
|
||||
auto contentWidth = this->GetContentWidth() - 2; /* subtract padding */
|
||||
auto contentHeight = this->height - 4; /* top and bottom padding + title */
|
||||
auto startX = 1; /* L padding */
|
||||
auto startY = 2; /* below the title, plus an extra space */
|
||||
auto listWidth = scrollbar ? contentWidth - 2 : contentWidth;
|
||||
|
||||
this->listWindow->MoveAndResize(startX, startY, listWidth, contentHeight);
|
||||
|
||||
auto index = this->listWindow->GetSelectedIndex();
|
||||
if (!this->listWindow->IsEntryVisible(index)) {
|
||||
this->listWindow->ScrollTo(index);
|
||||
}
|
||||
|
||||
if (scrollbar) {
|
||||
this->scrollbar->Show();
|
||||
this->scrollbar->MoveAndResize(contentWidth, startY, 1, contentHeight);
|
||||
}
|
||||
else {
|
||||
this->scrollbar->Hide();
|
||||
}
|
||||
|
||||
this->Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
bool ListOverlay::ScrollbarVisible() {
|
||||
#ifndef __FreeBSD__
|
||||
auto contentHeight = this->height - 4; /* top and bottom padding + title */
|
||||
return (int) this->listWindow->EntryCount() > contentHeight;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
ListOverlay& ListOverlay::SetTitle(const std::string& title) {
|
||||
this->title = title;
|
||||
this->RecalculateSize();
|
||||
|
@ -72,8 +72,11 @@ namespace cursespp {
|
||||
virtual void OnVisibilityChanged(bool visible);
|
||||
|
||||
private:
|
||||
class CustomListWindow;
|
||||
|
||||
void Redraw();
|
||||
void RecalculateSize();
|
||||
bool ScrollbarVisible();
|
||||
|
||||
std::string title;
|
||||
int x, y;
|
||||
@ -81,7 +84,8 @@ namespace cursespp {
|
||||
int setWidth, setWidthPercent;
|
||||
bool autoDismiss;
|
||||
IScrollAdapterPtr adapter;
|
||||
std::shared_ptr<ListWindow> listWindow;
|
||||
std::shared_ptr<CustomListWindow> listWindow;
|
||||
std::shared_ptr<Window> scrollbar;
|
||||
ItemSelectedCallback itemSelectedCallback;
|
||||
DeleteKeyCallback deleteKeyCallback;
|
||||
};
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <stdafx.h>
|
||||
#include <algorithm>
|
||||
#include "ListWindow.h"
|
||||
#include "Scrollbar.h"
|
||||
|
||||
using namespace cursespp;
|
||||
|
||||
@ -71,35 +72,9 @@ void ListWindow::Invalidate() {
|
||||
}
|
||||
|
||||
void ListWindow::DecorateFrame() {
|
||||
#ifndef __FreeBSD__
|
||||
if (this->showScrollbar) {
|
||||
int height = this->GetHeight();
|
||||
auto *adapter = &this->GetScrollAdapter();
|
||||
if (adapter && this->IsFrameVisible() && height > 2) {
|
||||
auto& pos = this->GetScrollPosition();
|
||||
float range = (float)height - 2.0f;
|
||||
float total = (float)std::max((size_t)1, adapter->GetEntryCount());
|
||||
|
||||
int offset;
|
||||
if (range > total) {
|
||||
offset = -1;
|
||||
}
|
||||
else {
|
||||
float percent = (float)pos.logicalIndex / total;
|
||||
offset = (int)(range * percent) + 1;
|
||||
}
|
||||
|
||||
auto frame = this->GetFrame();
|
||||
|
||||
for (int i = 1; i < height - 1; i++) {
|
||||
wmove(frame, i, this->GetWidth() - 1);
|
||||
if (i == offset) wattron(frame, A_REVERSE);
|
||||
waddch(frame, (i == offset) ? ' ' : ACS_VLINE);
|
||||
if (i == offset) wattroff(frame, A_REVERSE);
|
||||
}
|
||||
}
|
||||
if (this->IsFrameVisible()) {
|
||||
Scrollbar::Draw(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ListWindow::ScrollToTop() {
|
||||
|
@ -82,6 +82,8 @@ namespace cursespp {
|
||||
virtual const IScrollAdapter::ScrollPosition& GetScrollPosition();
|
||||
|
||||
protected:
|
||||
friend class Scrollbar;
|
||||
|
||||
virtual IScrollAdapter& GetScrollAdapter();
|
||||
virtual IScrollAdapter::ScrollPosition& GetMutableScrollPosition();
|
||||
virtual void OnRedraw();
|
||||
|
87
src/musikcube/cursespp/Scrollbar.cpp
Normal file
87
src/musikcube/cursespp/Scrollbar.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Scrollbar.h"
|
||||
|
||||
using namespace cursespp;
|
||||
|
||||
void Scrollbar::Draw(ListWindow* list, Window* target) {
|
||||
#ifndef __FreeBSD__
|
||||
int height = list->GetHeight();
|
||||
auto *adapter = &list->GetScrollAdapter();
|
||||
if (adapter && height > 2) {
|
||||
auto& pos = list->GetScrollPosition();
|
||||
|
||||
/* these are defaults for drawing to an external view, that
|
||||
is, when target != list. */
|
||||
int xOffset = 0;
|
||||
int from = 0, to = height;
|
||||
WINDOW* frame = nullptr;
|
||||
float range = (float) height;
|
||||
size_t minY = 0;
|
||||
|
||||
if (!target || target == list) {
|
||||
/* if we're drawing on top of the ListWindow's frame,
|
||||
we need to account for the padding it provides. */
|
||||
frame = list->GetFrame();
|
||||
xOffset = list->GetWidth() - 1;
|
||||
++from; --to;
|
||||
range -= 2.0f;
|
||||
minY = 1;
|
||||
}
|
||||
else {
|
||||
frame = target->GetFrame();
|
||||
}
|
||||
|
||||
float total = (float) std::max(minY, adapter->GetEntryCount());
|
||||
|
||||
int yOffset;
|
||||
if (range > total) {
|
||||
yOffset = -1;
|
||||
}
|
||||
else {
|
||||
float percent = (float)pos.logicalIndex / total;
|
||||
yOffset = (int)(range * percent) + minY;
|
||||
}
|
||||
|
||||
for (int i = from; i < to; i++) {
|
||||
wmove(frame, i, xOffset);
|
||||
if (i == yOffset) wattron(frame, A_REVERSE);
|
||||
waddch(frame, (i == yOffset) ? ' ' : ACS_VLINE);
|
||||
if (i == yOffset) wattroff(frame, A_REVERSE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
44
src/musikcube/cursespp/Scrollbar.h
Normal file
44
src/musikcube/cursespp/Scrollbar.h
Normal file
@ -0,0 +1,44 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "ListWindow.h"
|
||||
|
||||
namespace cursespp {
|
||||
class Scrollbar {
|
||||
public:
|
||||
static void Draw(ListWindow* window, Window* target = nullptr);
|
||||
};
|
||||
}
|
@ -239,7 +239,7 @@ void Window::MoveAndResize(int x, int y, int width, int height) {
|
||||
absX != this->lastAbsoluteX ||
|
||||
absY != this->lastAbsoluteY;
|
||||
|
||||
if (sizeChanged || positionChanged || badBounds) {
|
||||
if (sizeChanged || positionChanged || this->badBounds || !this->content) {
|
||||
this->lastAbsoluteX = absX;
|
||||
this->lastAbsoluteY = absY;
|
||||
this->width = width;
|
||||
|
@ -180,6 +180,7 @@ xcopy "$(SolutionDir)src\3rdparty\bin\win32\dll\vorbis\*" "$(TargetDir)" /Y /e</
|
||||
<ClCompile Include="cursespp\Screen.cpp" />
|
||||
<ClCompile Include="cursespp\ScrollableWindow.cpp" />
|
||||
<ClCompile Include="cursespp\ScrollAdapterBase.cpp" />
|
||||
<ClCompile Include="cursespp\Scrollbar.cpp" />
|
||||
<ClCompile Include="cursespp\ShortcutsWindow.cpp" />
|
||||
<ClCompile Include="cursespp\SimpleScrollAdapter.cpp" />
|
||||
<ClCompile Include="cursespp\SingleLineEntry.cpp" />
|
||||
@ -253,6 +254,7 @@ xcopy "$(SolutionDir)src\3rdparty\bin\win32\dll\vorbis\*" "$(TargetDir)" /Y /e</
|
||||
<ClInclude Include="cursespp\Screen.h" />
|
||||
<ClInclude Include="cursespp\ScrollableWindow.h" />
|
||||
<ClInclude Include="cursespp\ScrollAdapterBase.h" />
|
||||
<ClInclude Include="cursespp\Scrollbar.h" />
|
||||
<ClInclude Include="cursespp\ShortcutsWindow.h" />
|
||||
<ClInclude Include="cursespp\SimpleScrollAdapter.h" />
|
||||
<ClInclude Include="cursespp\SingleLineEntry.h" />
|
||||
|
@ -150,6 +150,9 @@
|
||||
<ClCompile Include="app\overlay\BrowseOverlays.cpp">
|
||||
<Filter>app\overlay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cursespp\Scrollbar.cpp">
|
||||
<Filter>cursespp\util</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h" />
|
||||
@ -352,6 +355,9 @@
|
||||
<ClInclude Include="app\overlay\BrowseOverlays.h">
|
||||
<Filter>app\overlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="cursespp\Scrollbar.h">
|
||||
<Filter>cursespp\util</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="cursespp">
|
||||
|
Loading…
x
Reference in New Issue
Block a user