mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-06 23:24:01 +02:00
Simplified setup of drag'n'drop area.
This commit is contained in:
parent
d98212e8b3
commit
9bf2940375
3 changed files with 215 additions and 7 deletions
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "history/history_drag_area.h"
|
#include "history/history_drag_area.h"
|
||||||
|
|
||||||
|
#include "base/event_filter.h"
|
||||||
#include "boxes/confirm_box.h"
|
#include "boxes/confirm_box.h"
|
||||||
#include "boxes/sticker_set_box.h"
|
#include "boxes/sticker_set_box.h"
|
||||||
#include "inline_bots/inline_bot_result.h"
|
#include "inline_bots/inline_bot_result.h"
|
||||||
|
@ -21,10 +22,209 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
|
#include "storage/storage_media_prepare.h"
|
||||||
#include "styles/style_chat_helpers.h"
|
#include "styles/style_chat_helpers.h"
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
|
|
||||||
DragArea::DragArea(QWidget *parent) : TWidget(parent) {
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto kDragAreaEvents = {
|
||||||
|
QEvent::DragEnter,
|
||||||
|
QEvent::DragLeave,
|
||||||
|
QEvent::Drop,
|
||||||
|
QEvent::MouseButtonRelease,
|
||||||
|
QEvent::Leave,
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
DragArea::Areas DragArea::SetupDragAreaToContainer(
|
||||||
|
not_null<Ui::RpWidget*> container,
|
||||||
|
Fn<bool()> &&dragEnterFilter,
|
||||||
|
Fn<void(bool)> &&setAcceptDropsField,
|
||||||
|
Fn<void()> &&updateControlsGeometry) {
|
||||||
|
|
||||||
|
using DragState = Storage::MimeDataState;
|
||||||
|
|
||||||
|
auto &lifetime = container->lifetime();
|
||||||
|
container->setAcceptDrops(true);
|
||||||
|
|
||||||
|
const auto attachDragDocument = Ui::CreateChild<DragArea>(container.get());
|
||||||
|
const auto attachDragPhoto = Ui::CreateChild<DragArea>(container.get());
|
||||||
|
|
||||||
|
attachDragDocument->hide();
|
||||||
|
attachDragPhoto->hide();
|
||||||
|
|
||||||
|
attachDragDocument->raise();
|
||||||
|
attachDragPhoto->raise();
|
||||||
|
|
||||||
|
const auto attachDragState =
|
||||||
|
lifetime.make_state<DragState>(DragState::None);
|
||||||
|
|
||||||
|
const auto width = [=] {
|
||||||
|
return container->width();
|
||||||
|
};
|
||||||
|
const auto height = [=] {
|
||||||
|
return container->height();
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto horizontalMargins = st::dragMargin.left()
|
||||||
|
+ st::dragMargin.right();
|
||||||
|
const auto verticalMargins = st::dragMargin.top()
|
||||||
|
+ st::dragMargin.bottom();
|
||||||
|
const auto resizeToFull = [=](not_null<DragArea*> w) {
|
||||||
|
w->resize(width() - horizontalMargins, height() - verticalMargins);
|
||||||
|
};
|
||||||
|
const auto moveToTop = [=](not_null<DragArea*> w) {
|
||||||
|
w->move(st::dragMargin.left(), st::dragMargin.top());
|
||||||
|
};
|
||||||
|
const auto updateAttachGeometry = crl::guard(container, [=] {
|
||||||
|
if (updateControlsGeometry) {
|
||||||
|
updateControlsGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (*attachDragState) {
|
||||||
|
case DragState::Files:
|
||||||
|
resizeToFull(attachDragDocument);
|
||||||
|
moveToTop(attachDragDocument);
|
||||||
|
break;
|
||||||
|
case DragState::PhotoFiles:
|
||||||
|
attachDragDocument->resize(
|
||||||
|
width() - horizontalMargins,
|
||||||
|
(height() - verticalMargins) / 2);
|
||||||
|
moveToTop(attachDragDocument);
|
||||||
|
attachDragPhoto->resize(
|
||||||
|
attachDragDocument->width(),
|
||||||
|
attachDragDocument->height());
|
||||||
|
attachDragPhoto->move(
|
||||||
|
st::dragMargin.left(),
|
||||||
|
height()
|
||||||
|
- attachDragPhoto->height()
|
||||||
|
- st::dragMargin.bottom());
|
||||||
|
break;
|
||||||
|
case DragState::Image:
|
||||||
|
resizeToFull(attachDragPhoto);
|
||||||
|
moveToTop(attachDragPhoto);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto updateDragAreas = [=] {
|
||||||
|
if (setAcceptDropsField) {
|
||||||
|
setAcceptDropsField(*attachDragState == DragState::None);
|
||||||
|
}
|
||||||
|
updateAttachGeometry();
|
||||||
|
|
||||||
|
switch (*attachDragState) {
|
||||||
|
case DragState::None:
|
||||||
|
attachDragDocument->otherLeave();
|
||||||
|
attachDragPhoto->otherLeave();
|
||||||
|
break;
|
||||||
|
case DragState::Files:
|
||||||
|
attachDragDocument->setText(
|
||||||
|
tr::lng_drag_files_here(tr::now),
|
||||||
|
tr::lng_drag_to_send_files(tr::now));
|
||||||
|
attachDragDocument->otherEnter();
|
||||||
|
attachDragPhoto->hideFast();
|
||||||
|
break;
|
||||||
|
case DragState::PhotoFiles:
|
||||||
|
attachDragDocument->setText(
|
||||||
|
tr::lng_drag_images_here(tr::now),
|
||||||
|
tr::lng_drag_to_send_no_compression(tr::now));
|
||||||
|
attachDragPhoto->setText(
|
||||||
|
tr::lng_drag_photos_here(tr::now),
|
||||||
|
tr::lng_drag_to_send_quick(tr::now));
|
||||||
|
attachDragDocument->otherEnter();
|
||||||
|
attachDragPhoto->otherEnter();
|
||||||
|
break;
|
||||||
|
case DragState::Image:
|
||||||
|
attachDragPhoto->setText(
|
||||||
|
tr::lng_drag_images_here(tr::now),
|
||||||
|
tr::lng_drag_to_send_quick(tr::now));
|
||||||
|
attachDragDocument->hideFast();
|
||||||
|
attachDragPhoto->otherEnter();
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
container->sizeValue(
|
||||||
|
) | rpl::start_with_next(updateAttachGeometry, lifetime);
|
||||||
|
|
||||||
|
const auto resetDragStateIfNeeded = [=] {
|
||||||
|
if (*attachDragState != DragState::None
|
||||||
|
|| !attachDragPhoto->isHidden()
|
||||||
|
|| !attachDragDocument->isHidden()) {
|
||||||
|
*attachDragState = DragState::None;
|
||||||
|
updateDragAreas();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto dragEnterEvent = [=](QDragEnterEvent *e) {
|
||||||
|
if (dragEnterFilter && dragEnterFilter()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*attachDragState = Storage::ComputeMimeDataState(e->mimeData());
|
||||||
|
updateDragAreas();
|
||||||
|
|
||||||
|
if (*attachDragState != DragState::None) {
|
||||||
|
e->setDropAction(Qt::IgnoreAction);
|
||||||
|
e->accept();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto dragLeaveEvent = [=](QDragLeaveEvent *e) {
|
||||||
|
resetDragStateIfNeeded();
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto dropEvent = [=](QDropEvent *e) {
|
||||||
|
*attachDragState = DragState::None;
|
||||||
|
updateDragAreas();
|
||||||
|
e->acceptProposedAction();
|
||||||
|
};
|
||||||
|
|
||||||
|
container->events(
|
||||||
|
) | rpl::filter([=](not_null<QEvent*> event) {
|
||||||
|
return ranges::contains(kDragAreaEvents, event->type());
|
||||||
|
}) | rpl::start_with_next([=](not_null<QEvent*> event) {
|
||||||
|
const auto type = event->type();
|
||||||
|
|
||||||
|
if (type == QEvent::DragEnter) {
|
||||||
|
dragEnterEvent(static_cast<QDragEnterEvent*>(event.get()));
|
||||||
|
} else if (type == QEvent::DragLeave) {
|
||||||
|
dragLeaveEvent(static_cast<QDragLeaveEvent*>(event.get()));
|
||||||
|
} else if (type == QEvent::Drop) {
|
||||||
|
dropEvent(static_cast<QDropEvent*>(event.get()));
|
||||||
|
} else if (type == QEvent::Leave) {
|
||||||
|
resetDragStateIfNeeded();
|
||||||
|
} else if (type == QEvent::MouseButtonRelease) {
|
||||||
|
resetDragStateIfNeeded();
|
||||||
|
}
|
||||||
|
}, lifetime);
|
||||||
|
|
||||||
|
const auto eventFilter = [=](not_null<QEvent*> event) {
|
||||||
|
const auto type = event->type();
|
||||||
|
if (type == QEvent::DragEnter) {
|
||||||
|
dragEnterEvent(static_cast<QDragEnterEvent*>(event.get()));
|
||||||
|
} else if (type == QEvent::DragLeave) {
|
||||||
|
dragLeaveEvent(static_cast<QDragLeaveEvent*>(event.get()));
|
||||||
|
} else if (type == QEvent::Drop) {
|
||||||
|
dropEvent(static_cast<QDropEvent*>(event.get()));
|
||||||
|
}
|
||||||
|
return base::EventFilterResult::Continue;
|
||||||
|
};
|
||||||
|
base::install_event_filter(attachDragDocument, eventFilter);
|
||||||
|
base::install_event_filter(attachDragPhoto, eventFilter);
|
||||||
|
|
||||||
|
updateDragAreas();
|
||||||
|
|
||||||
|
return {
|
||||||
|
.photo = attachDragPhoto,
|
||||||
|
.document = attachDragDocument
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
DragArea::DragArea(QWidget *parent) : Ui::RpWidget(parent) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
}
|
}
|
||||||
|
@ -96,18 +296,15 @@ void DragArea::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DragArea::dragEnterEvent(QDragEnterEvent *e) {
|
void DragArea::dragEnterEvent(QDragEnterEvent *e) {
|
||||||
static_cast<HistoryWidget*>(parentWidget())->dragEnterEvent(e);
|
|
||||||
e->setDropAction(Qt::IgnoreAction);
|
e->setDropAction(Qt::IgnoreAction);
|
||||||
e->accept();
|
e->accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DragArea::dragLeaveEvent(QDragLeaveEvent *e) {
|
void DragArea::dragLeaveEvent(QDragLeaveEvent *e) {
|
||||||
static_cast<HistoryWidget*>(parentWidget())->dragLeaveEvent(e);
|
|
||||||
setIn(false);
|
setIn(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DragArea::dropEvent(QDropEvent *e) {
|
void DragArea::dropEvent(QDropEvent *e) {
|
||||||
static_cast<HistoryWidget*>(parentWidget())->dropEvent(e);
|
|
||||||
if (e->isAccepted() && _droppedCallback) {
|
if (e->isAccepted() && _droppedCallback) {
|
||||||
_droppedCallback(e->mimeData());
|
_droppedCallback(e->mimeData());
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
|
|
||||||
class DragArea : public TWidget {
|
class DragArea : public Ui::RpWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DragArea(QWidget *parent);
|
DragArea(QWidget *parent);
|
||||||
|
|
||||||
|
struct Areas {
|
||||||
|
DragArea *document;
|
||||||
|
DragArea *photo;
|
||||||
|
};
|
||||||
|
static Areas SetupDragAreaToContainer(
|
||||||
|
not_null<Ui::RpWidget*> container,
|
||||||
|
Fn<bool()> &&dragEnterFilter = nullptr,
|
||||||
|
Fn<void(bool)> &&setAcceptDropsField = nullptr,
|
||||||
|
Fn<void()> &&updateControlsGeometry = nullptr);
|
||||||
|
|
||||||
void setText(const QString &text, const QString &subtext);
|
void setText(const QString &text, const QString &subtext);
|
||||||
|
|
||||||
void otherEnter();
|
void otherEnter();
|
||||||
|
@ -32,10 +42,11 @@ public:
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
void mouseMoveEvent(QMouseEvent *e) override;
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
|
void dragMoveEvent(QDragMoveEvent *e) override;
|
||||||
|
// These events should be filtered by parent!
|
||||||
void dragEnterEvent(QDragEnterEvent *e) override;
|
void dragEnterEvent(QDragEnterEvent *e) override;
|
||||||
void dragLeaveEvent(QDragLeaveEvent *e) override;
|
void dragLeaveEvent(QDragLeaveEvent *e) override;
|
||||||
void dropEvent(QDropEvent *e) override;
|
void dropEvent(QDropEvent *e) override;
|
||||||
void dragMoveEvent(QDragMoveEvent *e) override;
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void hideStart();
|
void hideStart();
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 88a4a27d8e5d02b83b5487d5f156bf45e7ae14ee
|
Subproject commit 34eb5a8eb802dbbf9e5c9516e55a04af6b87aeb2
|
Loading…
Add table
Reference in a new issue