1 // This file is part of Desktop App Toolkit,
2 // a set of libraries for developing nice desktop applications.
3 //
4 // For license and copyright information please follow this link:
5 // https://github.com/desktop-app/legal/blob/master/LEGAL
6 //
7 #pragma once
8 
9 #include "base/basic_types.h"
10 
11 #include <QtCore/QVariant>
12 
13 class ClickHandler;
14 using ClickHandlerPtr = std::shared_ptr<ClickHandler>;
15 
16 struct ClickContext {
17 	Qt::MouseButton button = Qt::LeftButton;
18 	QVariant other;
19 };
20 
21 class ClickHandlerHost {
22 protected:
clickHandlerActiveChanged(const ClickHandlerPtr & action,bool active)23 	virtual void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
24 	}
clickHandlerPressedChanged(const ClickHandlerPtr & action,bool pressed)25 	virtual void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) {
26 	}
27 	virtual ~ClickHandlerHost() = 0;
28 	friend class ClickHandler;
29 
30 };
31 
32 enum class EntityType : uchar;
33 class ClickHandler {
34 public:
~ClickHandler()35 	virtual ~ClickHandler() {
36 	}
37 
38 	virtual void onClick(ClickContext context) const = 0;
39 
40 	// What text to show in a tooltip when mouse is over that click handler as a link in Text.
tooltip()41 	virtual QString tooltip() const {
42 		return QString();
43 	}
44 
45 	// What to drop in the input fields when dragging that click handler as a link from Text.
dragText()46 	virtual QString dragText() const {
47 		return QString();
48 	}
49 
50 	// Copy to clipboard support.
copyToClipboardText()51 	virtual QString copyToClipboardText() const {
52 		return QString();
53 	}
copyToClipboardContextItemText()54 	virtual QString copyToClipboardContextItemText() const {
55 		return QString();
56 	}
57 
58 	// Entities in text support.
59 	struct TextEntity {
60 		EntityType type = EntityType();
61 		QString data;
62 	};
63 	virtual TextEntity getTextEntity() const;
64 
65 	// This method should be called on mouse over a click handler.
66 	// It returns true if the active handler was changed or false otherwise.
67 	static bool setActive(const ClickHandlerPtr &p, ClickHandlerHost *host = nullptr);
68 
69 	// This method should be called when mouse leaves the host.
70 	// It returns true if the active handler was changed or false otherwise.
71 	static bool clearActive(ClickHandlerHost *host = nullptr);
72 
73 	// This method should be called on mouse press event.
74 	static void pressed();
75 
76 	// This method should be called on mouse release event.
77 	// The activated click handler (if any) is returned.
78 	static ClickHandlerPtr unpressed();
79 
80 	static ClickHandlerPtr getActive();
81 	static ClickHandlerPtr getPressed();
82 
83 	static bool showAsActive(const ClickHandlerPtr &p);
84 	static bool showAsPressed(const ClickHandlerPtr &p);
85 	static void hostDestroyed(ClickHandlerHost *host);
86 
87 private:
88 	static ClickHandlerHost *_activeHost;
89 	static ClickHandlerHost *_pressedHost;
90 
91 };
92 
93 class LeftButtonClickHandler : public ClickHandler {
94 public:
onClick(ClickContext context)95 	void onClick(ClickContext context) const override final {
96 		if (context.button == Qt::LeftButton) {
97 			onClickImpl();
98 		}
99 	}
100 
101 protected:
102 	virtual void onClickImpl() const = 0;
103 
104 };
105 
106 class LambdaClickHandler : public ClickHandler {
107 public:
LambdaClickHandler(Fn<void ()> handler)108 	LambdaClickHandler(Fn<void()> handler)
109 	: _handler([handler = std::move(handler)](ClickContext) { handler(); }) {
110 	}
LambdaClickHandler(Fn<void (ClickContext)> handler)111 	LambdaClickHandler(Fn<void(ClickContext)> handler)
112 	: _handler(std::move(handler)) {
113 	}
onClick(ClickContext context)114 	void onClick(ClickContext context) const override final {
115 		if (context.button == Qt::LeftButton && _handler) {
116 			_handler(context);
117 		}
118 	}
119 
120 private:
121 	Fn<void(ClickContext)> _handler;
122 
123 };
124 
125 void ActivateClickHandler(
126 	not_null<QWidget*> guard,
127 	ClickHandlerPtr handler,
128 	ClickContext context);
129 void ActivateClickHandler(
130 	not_null<QWidget*> guard,
131 	ClickHandlerPtr handler,
132 	Qt::MouseButton button);
133