mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-08 22:13:23 +00:00
Add possibility to pin/unpin recent items
This commit is contained in:
parent
57a8bbdf19
commit
72313e1c48
@ -654,6 +654,15 @@
|
||||
<style id="recent_file_detail" border="2" border-left="0" extends="recent_file">
|
||||
<text color="disabled" align="left" x="2" />
|
||||
</style>
|
||||
<style id="recent_file_pin">
|
||||
<background color="background" />
|
||||
<background color="menuitem_hot_face" state="mouse" />
|
||||
<background color="listitem_selected_face" state="selected" />
|
||||
<icon part="unpinned" align="center middle" color="text" />
|
||||
<icon part="unpinned" align="center middle" color="listitem_selected_text" state="selected" />
|
||||
<icon part="pinned" align="center middle" color="text" state="focus" />
|
||||
<icon part="pinned" align="center middle" color="listitem_selected_text" state="focus selected" />
|
||||
</style>
|
||||
<style id="news_item" border="2">
|
||||
<background color="background" />
|
||||
<background color="menuitem_hot_face" state="mouse" />
|
||||
|
2
laf
2
laf
@ -1 +1 @@
|
||||
Subproject commit 950f62c1ccff7cf59c220e9016ead0845767e546
|
||||
Subproject commit 3355825d61b8d0d92ffdea970fd9e1434bd4ecca
|
@ -95,12 +95,20 @@ public:
|
||||
return m_wasDragged;
|
||||
}
|
||||
|
||||
bool isDragging() const {
|
||||
return m_isDragging;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void createFloatingOverlay() {
|
||||
ASSERT(!m_floatingOverlay);
|
||||
|
||||
m_isDragging = true;
|
||||
|
||||
gfx::Size sz = getFloatingOverlaySize();
|
||||
sz.w = std::max(1, sz.w);
|
||||
sz.h = std::max(1, sz.h);
|
||||
os::Surface* surface = os::instance()->createRgbaSurface(sz.w, sz.h);
|
||||
|
||||
{
|
||||
@ -122,6 +130,7 @@ private:
|
||||
void destroyFloatingOverlay() {
|
||||
ui::OverlayManager::instance()->removeOverlay(m_floatingOverlay.get());
|
||||
m_floatingOverlay.reset();
|
||||
m_isDragging = false;
|
||||
}
|
||||
|
||||
gfx::Size getFloatingOverlaySize() {
|
||||
@ -129,7 +138,7 @@ private:
|
||||
if (!view)
|
||||
view = ui::View::getView(this->parent());
|
||||
if (view)
|
||||
return (view->viewportBounds() & this->bounds()).size();
|
||||
return (view->viewportBounds().offset(view->viewScroll()) & this->bounds()).size();
|
||||
else
|
||||
return this->size();
|
||||
}
|
||||
@ -146,6 +155,8 @@ private:
|
||||
// widget bounds.
|
||||
bool m_createFloatingOverlay = false;
|
||||
|
||||
bool m_isDragging = false;
|
||||
|
||||
// True when the mouse button is released (drop operation) and we've
|
||||
// dragged the widget to other position. Can be used to avoid
|
||||
// triggering the default click operation by derived classes when
|
||||
|
@ -121,8 +121,6 @@ void EditorView::onSetViewScroll(const gfx::Point& pt)
|
||||
|
||||
void EditorView::onScrollRegion(ui::ScrollRegionEvent& ev)
|
||||
{
|
||||
View::onScrollRegion(ev);
|
||||
|
||||
gfx::Region& region = ev.region();
|
||||
Editor* editor = this->editor();
|
||||
ASSERT(editor);
|
||||
|
@ -17,8 +17,6 @@ namespace app {
|
||||
|
||||
void FileListView::onScrollRegion(ui::ScrollRegionEvent& ev)
|
||||
{
|
||||
View::onScrollRegion(ev);
|
||||
|
||||
if (auto fileList = dynamic_cast<FileList*>(attachedWidget())) {
|
||||
gfx::Rect tbounds = fileList->thumbnailBounds();
|
||||
if (!tbounds.isEmpty()) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "ui/listitem.h"
|
||||
#include "ui/message.h"
|
||||
#include "ui/paint_event.h"
|
||||
#include "ui/scroll_region_event.h"
|
||||
#include "ui/size_hint_event.h"
|
||||
#include "ui/system.h"
|
||||
#include "ui/view.h"
|
||||
@ -51,6 +52,16 @@ public:
|
||||
}
|
||||
|
||||
const std::string& fullpath() const { return m_fullpath; }
|
||||
bool pinned() const { return m_pinned; }
|
||||
|
||||
void pin() {
|
||||
m_pinned = true;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void onScrollRegion(ui::ScrollRegionEvent& ev) {
|
||||
ev.region() -= gfx::Region(pinBounds(bounds()));
|
||||
}
|
||||
|
||||
protected:
|
||||
void onInitTheme(InitThemeEvent& ev) override {
|
||||
@ -72,6 +83,52 @@ protected:
|
||||
ev.setSizeHint(gfx::Size(sz1.w+sz2.w, MAX(sz1.h, sz2.h)));
|
||||
}
|
||||
|
||||
bool onProcessMessage(Message* msg) override {
|
||||
switch (msg->type()) {
|
||||
case kMouseDownMessage: {
|
||||
const gfx::Point mousePos = static_cast<MouseMessage*>(msg)->position();
|
||||
gfx::Rect rc = pinBounds(bounds());
|
||||
rc.y = bounds().y;
|
||||
rc.h = bounds().h;
|
||||
if (rc.contains(mousePos)) {
|
||||
m_pinned = !m_pinned;
|
||||
invalidate();
|
||||
|
||||
auto parent = this->parent();
|
||||
const auto& children = parent->children();
|
||||
auto end = children.end();
|
||||
auto moveTo = parent->firstChild();
|
||||
if (m_pinned) {
|
||||
for (auto it=children.begin(); it != end; ++it) {
|
||||
if (*it == this || !static_cast<RecentFileItem*>(*it)->pinned()) {
|
||||
moveTo = *it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
auto it = std::find(children.begin(), end, this);
|
||||
if (it != end) {
|
||||
auto prevIt = it++;
|
||||
for (; it != end; prevIt=it++) {
|
||||
if (!static_cast<RecentFileItem*>(*it)->pinned())
|
||||
break;
|
||||
}
|
||||
moveTo = *prevIt;
|
||||
}
|
||||
}
|
||||
if (this != moveTo) {
|
||||
parent->moveChildTo(this, moveTo);
|
||||
parent->layout();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return DraggableWidget<LinkLabel>::onProcessMessage(msg);
|
||||
}
|
||||
|
||||
void onPaint(PaintEvent& ev) override {
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
|
||||
Graphics* g = ev.graphics();
|
||||
@ -90,6 +147,17 @@ protected:
|
||||
setTextQuiet(m_path.c_str());
|
||||
theme->paintWidget(g, this, styleDetail, detailsBounds);
|
||||
}
|
||||
|
||||
if (!isDragging() && (m_pinned || hasMouse())) {
|
||||
ui::Style* pinStyle = theme->styles.recentFilePin();
|
||||
const gfx::Rect pinBounds = this->pinBounds(bounds);
|
||||
PaintWidgetPartInfo pi;
|
||||
pi.styleFlags =
|
||||
(isSelected() ? ui::Style::Layer::kSelected: 0) |
|
||||
(m_pinned ? ui::Style::Layer::kFocus: 0) |
|
||||
(hasMouse() ? ui::Style::Layer::kMouse: 0);
|
||||
theme->paintWidgetPart(g, pinStyle, pinBounds, pi);
|
||||
}
|
||||
}
|
||||
|
||||
void onClick() override {
|
||||
@ -107,14 +175,39 @@ protected:
|
||||
}
|
||||
|
||||
void onFinalDrop() override {
|
||||
if (wasDragged())
|
||||
static_cast<RecentListBox*>(parent())->updateRecentListFromUIItems();
|
||||
if (!wasDragged())
|
||||
return;
|
||||
|
||||
// Pin all elements to keep the order
|
||||
const auto& children = parent()->children();
|
||||
for (auto it=children.rbegin(), end=children.rend(); it!=end; ++it) {
|
||||
if (this == *it) {
|
||||
for (; it!=end; ++it)
|
||||
static_cast<RecentFileItem*>(*it)->pin();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static_cast<RecentListBox*>(parent())->updateRecentListFromUIItems();
|
||||
}
|
||||
|
||||
private:
|
||||
gfx::Rect pinBounds(const gfx::Rect& bounds) {
|
||||
SkinTheme* theme = static_cast<SkinTheme*>(this->theme());
|
||||
ui::Style* pinStyle = theme->styles.recentFilePin();
|
||||
ui::View* view = View::getView(parent());
|
||||
const gfx::Size pinSize = theme->calcSizeHint(this, pinStyle);
|
||||
const gfx::Rect vp = view->viewportBounds();
|
||||
const gfx::Point scroll = view->viewScroll();
|
||||
return gfx::Rect(scroll.x+bounds.x+vp.w-pinSize.w,
|
||||
bounds.y+bounds.h/2-pinSize.h/2,
|
||||
pinSize.w, pinSize.h);
|
||||
}
|
||||
|
||||
std::string m_fullpath;
|
||||
std::string m_name;
|
||||
std::string m_path;
|
||||
bool m_pinned = false;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@ -156,6 +249,12 @@ void RecentListBox::updateRecentListFromUIItems()
|
||||
onUpdateRecentListFromUIItems(paths);
|
||||
}
|
||||
|
||||
void RecentListBox::onScrollRegion(ui::ScrollRegionEvent& ev)
|
||||
{
|
||||
for (auto item : children())
|
||||
static_cast<RecentFileItem*>(item)->onScrollRegion(ev);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// RecentFilesListBox
|
||||
|
||||
|
@ -12,12 +12,14 @@
|
||||
#include "base/paths.h"
|
||||
#include "obs/connection.h"
|
||||
#include "ui/listbox.h"
|
||||
#include "ui/view.h"
|
||||
|
||||
namespace app {
|
||||
|
||||
class RecentFileItem;
|
||||
|
||||
class RecentListBox : public ui::ListBox {
|
||||
class RecentListBox : public ui::ListBox,
|
||||
public ui::ViewableWidget {
|
||||
friend class RecentFileItem;
|
||||
public:
|
||||
RecentListBox();
|
||||
@ -25,6 +27,9 @@ namespace app {
|
||||
void updateRecentListFromUIItems();
|
||||
|
||||
protected:
|
||||
// ui::ViewableWidget impl
|
||||
virtual void onScrollRegion(ui::ScrollRegionEvent& ev);
|
||||
|
||||
virtual void onRebuildList() = 0;
|
||||
virtual void onClick(const std::string& path) = 0;
|
||||
virtual void onUpdateRecentListFromUIItems(const base::paths& paths) = 0;
|
||||
|
@ -356,7 +356,8 @@ void View::onSetViewScroll(const gfx::Point& pt)
|
||||
|
||||
void View::onScrollRegion(ScrollRegionEvent& ev)
|
||||
{
|
||||
// Do nothing
|
||||
if (auto viewable = dynamic_cast<ViewableWidget*>(attachedWidget()))
|
||||
viewable->onScrollRegion(ev);
|
||||
}
|
||||
|
||||
void View::onScrollChange()
|
||||
|
@ -17,6 +17,12 @@
|
||||
namespace ui {
|
||||
class ScrollRegionEvent;
|
||||
|
||||
class ViewableWidget {
|
||||
public:
|
||||
virtual ~ViewableWidget() { }
|
||||
virtual void onScrollRegion(ScrollRegionEvent& ev) = 0;
|
||||
};
|
||||
|
||||
class View : public Widget
|
||||
, public ScrollableViewDelegate {
|
||||
public:
|
||||
|
Loading…
x
Reference in New Issue
Block a user