Move action_context into separate file

This commit is contained in:
patrick96 2021-02-03 19:29:09 +01:00 committed by Patrick Ziegler
parent 7a9f301830
commit c4fbf0023e
8 changed files with 229 additions and 209 deletions

View File

@ -10,7 +10,7 @@
#include "events/signal_fwd.hpp"
#include "events/signal_receiver.hpp"
#include "settings.hpp"
#include "tags/context.hpp"
#include "tags/action_context.hpp"
#include "utils/math.hpp"
#include "x11/types.hpp"
#include "x11/window.hpp"

View File

@ -2,6 +2,7 @@
#include <map>
#include "common.hpp"
#include "tags/action_context.hpp"
#include "tags/context.hpp"
POLYBAR_NS

View File

@ -0,0 +1,114 @@
#pragma once
#include <map>
#include "common.hpp"
#include "components/types.hpp"
POLYBAR_NS
namespace tags {
/**
* An identifier for an action block.
*
* A value of NO_ACTION denotes an undefined identifier and is guaranteed to
* be smaller (<) than any valid identifier.
*
* If two action blocks overlap, the action with the higher identifier will
* be above.
*
* Except for NO_ACTION, negative values are not allowed
*/
using action_t = int;
static constexpr action_t NO_ACTION = -1;
/**
* Defines a clickable (or scrollable) action block.
*
* An action block is an area on the bar that executes some command when clicked.
*/
struct action_block {
action_block(const string&& cmd, mousebtn button, alignment align, bool is_open)
: cmd(std::move(cmd)), button(button), align(align), is_open(is_open){};
string cmd;
/**
* Start position of the action block (inclusive), relative to the alignment.
*/
double start_x{0};
/**
* End position of the action block (exclusive), relative to the alignment.
*/
double end_x{0};
mousebtn button;
alignment align;
/**
* Tracks whether this block is still open or whether it already has a
* corresponding closing tag.
*
* After rendering, all action blocks should be closed.
*/
bool is_open;
unsigned int width() const {
return static_cast<unsigned int>(end_x - start_x + 0.5);
}
/**
* Tests whether a given point is inside this block.
*
* This additionally needs the position of the start of the alignment
* because the given point is relative to the bar window.
*/
bool test(double align_start, int point) const {
return static_cast<int>(start_x + align_start) <= point && static_cast<int>(end_x + align_start) > point;
}
};
class action_context {
public:
void reset();
action_t action_open(mousebtn btn, const string&& cmd, alignment align, double x);
std::pair<action_t, mousebtn> action_close(mousebtn btn, alignment align, double x);
void set_alignmnent_start(const alignment a, const double x);
std::map<mousebtn, tags::action_t> get_actions(int x) const;
action_t has_action(mousebtn btn, int x) const;
string get_action(action_t id) const;
bool has_double_click() const;
size_t num_actions() const;
size_t num_unclosed() const;
const std::vector<action_block>& get_blocks() const;
protected:
void set_start(action_t id, double x);
void set_end(action_t id, double x);
/**
* Stores all currently known action blocks.
*
* The action_t type is an index into this vector.
*/
std::vector<action_block> m_action_blocks;
/**
* Stores the x-coordinate for the start of all the alignment blocks.
*
* This is needed because the action block coordinates are relative to the
* alignment blocks and thus need the alignment block coordinates for
* intersection tests.
*/
std::map<alignment, double> m_align_start{
{alignment::NONE, 0}, {alignment::LEFT, 0}, {alignment::CENTER, 0}, {alignment::RIGHT, 0}};
};
} // namespace tags
POLYBAR_NS_END

View File

@ -1,7 +1,5 @@
#pragma once
#include <map>
#include "common.hpp"
#include "components/types.hpp"
#include "tags/types.hpp"
@ -82,108 +80,6 @@ namespace tags {
private:
const bar_settings& m_settings;
};
/**
* An identifier for an action block.
*
* A value of NO_ACTION denotes an undefined identifier and is guaranteed to
* be smaller (<) than any valid identifier.
*
* If two action blocks overlap, the action with the higher identifier will
* be above.
*
* Except for NO_ACTION, negative values are not allowed
*/
using action_t = int;
static constexpr action_t NO_ACTION = -1;
/**
* Defines a clickable (or scrollable) action block.
*
* An action block is an area on the bar that executes some command when clicked.
*/
struct action_block {
action_block(const string&& cmd, mousebtn button, alignment align, bool is_open)
: cmd(std::move(cmd)), button(button), align(align), is_open(is_open){};
string cmd;
/**
* Start position of the action block (inclusive), relative to the alignment.
*/
double start_x{0};
/**
* End position of the action block (exclusive), relative to the alignment.
*/
double end_x{0};
mousebtn button;
alignment align;
/**
* Tracks whether this block is still open or whether it already has a
* corresponding closing tag.
*
* After rendering, all action blocks should be closed.
*/
bool is_open;
unsigned int width() const {
return static_cast<unsigned int>(end_x - start_x + 0.5);
}
/**
* Tests whether a given point is inside this block.
*
* This additionally needs the position of the start of the alignment
* because the given point is relative to the bar window.
*/
bool test(double align_start, int point) const {
return static_cast<int>(start_x + align_start) <= point && static_cast<int>(end_x + align_start) > point;
}
};
class action_context {
public:
void reset();
action_t action_open(mousebtn btn, const string&& cmd, alignment align, double x);
std::pair<action_t, mousebtn> action_close(mousebtn btn, alignment align, double x);
void set_alignmnent_start(const alignment a, const double x);
std::map<mousebtn, tags::action_t> get_actions(int x) const;
action_t has_action(mousebtn btn, int x) const;
string get_action(action_t id) const;
bool has_double_click() const;
size_t num_actions() const;
size_t num_unclosed() const;
const std::vector<action_block>& get_blocks() const;
protected:
void set_start(action_t id, double x);
void set_end(action_t id, double x);
/**
* Stores all currently known action blocks.
*
* The action_t type is an index into this vector.
*/
std::vector<action_block> m_action_blocks;
/**
* Stores the x-coordinate for the start of all the alignment blocks.
*
* This is needed because the action block coordinates are relative to the
* alignment blocks and thus need the alignment block coordinates for
* intersection tests.
*/
std::map<alignment, double> m_align_start{
{alignment::NONE, 0}, {alignment::LEFT, 0}, {alignment::CENTER, 0}, {alignment::RIGHT, 0}};
};
} // namespace tags
POLYBAR_NS_END

View File

@ -96,6 +96,7 @@ if(BUILD_LIBPOLY)
${src_dir}/modules/xwindow.cpp
${src_dir}/modules/xworkspaces.cpp
${src_dir}/tags/action_context.cpp
${src_dir}/tags/context.cpp
${src_dir}/tags/dispatch.cpp
${src_dir}/tags/parser.cpp

110
src/tags/action_context.cpp Normal file
View File

@ -0,0 +1,110 @@
#include "tags/action_context.hpp"
#include <cassert>
POLYBAR_NS
namespace tags {
void action_context::reset() {
m_action_blocks.clear();
}
action_t action_context::action_open(mousebtn btn, const string&& cmd, alignment align, double x) {
action_t id = m_action_blocks.size();
m_action_blocks.emplace_back(std::move(cmd), btn, align, true);
set_start(id, x);
return id;
}
std::pair<action_t, mousebtn> action_context::action_close(mousebtn btn, alignment align, double x) {
for (auto it = m_action_blocks.rbegin(); it != m_action_blocks.rend(); it++) {
if (it->is_open && it->align == align && (btn == mousebtn::NONE || it->button == btn)) {
it->is_open = false;
// Converts a reverse iterator into an index
action_t id = std::distance(m_action_blocks.begin(), it.base()) - 1;
set_end(id, x);
return {id, it->button};
}
}
return {NO_ACTION, mousebtn::NONE};
}
void action_context::set_start(action_t id, double x) {
m_action_blocks[id].start_x = x;
}
void action_context::set_end(action_t id, double x) {
m_action_blocks[id].end_x = x;
}
void action_context::set_alignmnent_start(const alignment a, const double x) {
m_align_start[a] = x;
}
std::map<mousebtn, tags::action_t> action_context::get_actions(int x) const {
std::map<mousebtn, tags::action_t> buttons;
for (int i = static_cast<int>(mousebtn::NONE); i < static_cast<int>(mousebtn::BTN_COUNT); i++) {
buttons[static_cast<mousebtn>(i)] = tags::NO_ACTION;
}
for (action_t id = 0; (unsigned)id < m_action_blocks.size(); id++) {
auto action = m_action_blocks[id];
mousebtn btn = action.button;
// Higher IDs are higher in the action stack.
if (id > buttons[btn] && action.test(m_align_start.at(action.align), x)) {
buttons[action.button] = id;
}
}
return buttons;
}
action_t action_context::has_action(mousebtn btn, int x) const {
// TODO optimize
return get_actions(x)[btn];
}
string action_context::get_action(action_t id) const {
assert(id >= 0 && (unsigned)id < num_actions());
return m_action_blocks[id].cmd;
}
bool action_context::has_double_click() const {
for (auto&& a : m_action_blocks) {
if (a.button == mousebtn::DOUBLE_LEFT || a.button == mousebtn::DOUBLE_MIDDLE ||
a.button == mousebtn::DOUBLE_RIGHT) {
return true;
}
}
return false;
}
size_t action_context::num_actions() const {
return m_action_blocks.size();
}
size_t action_context::num_unclosed() const {
size_t num = 0;
for (const auto& a : m_action_blocks) {
if (a.is_open) {
num++;
}
}
return num;
}
const std::vector<action_block>& action_context::get_blocks() const {
return m_action_blocks;
}
} // namespace tags
POLYBAR_NS_END

View File

@ -1,7 +1,5 @@
#include "tags/context.hpp"
#include <cassert>
POLYBAR_NS
namespace tags {
@ -113,107 +111,6 @@ namespace tags {
alignment context::get_alignment() const {
return m_align;
}
void action_context::reset() {
m_action_blocks.clear();
}
action_t action_context::action_open(mousebtn btn, const string&& cmd, alignment align, double x) {
action_t id = m_action_blocks.size();
m_action_blocks.emplace_back(std::move(cmd), btn, align, true);
set_start(id, x);
return id;
}
std::pair<action_t, mousebtn> action_context::action_close(mousebtn btn, alignment align, double x) {
for (auto it = m_action_blocks.rbegin(); it != m_action_blocks.rend(); it++) {
if (it->is_open && it->align == align && (btn == mousebtn::NONE || it->button == btn)) {
it->is_open = false;
// Converts a reverse iterator into an index
action_t id = std::distance(m_action_blocks.begin(), it.base()) - 1;
set_end(id, x);
return {id, it->button};
}
}
return {NO_ACTION, mousebtn::NONE};
}
void action_context::set_start(action_t id, double x) {
m_action_blocks[id].start_x = x;
}
void action_context::set_end(action_t id, double x) {
m_action_blocks[id].end_x = x;
}
void action_context::set_alignmnent_start(const alignment a, const double x) {
m_align_start[a] = x;
}
std::map<mousebtn, tags::action_t> action_context::get_actions(int x) const {
std::map<mousebtn, tags::action_t> buttons;
for (int i = static_cast<int>(mousebtn::NONE); i < static_cast<int>(mousebtn::BTN_COUNT); i++) {
buttons[static_cast<mousebtn>(i)] = tags::NO_ACTION;
}
for (action_t id = 0; (unsigned)id < m_action_blocks.size(); id++) {
auto action = m_action_blocks[id];
mousebtn btn = action.button;
// Higher IDs are higher in the action stack.
if (id > buttons[btn] && action.test(m_align_start.at(action.align), x)) {
buttons[action.button] = id;
}
}
return buttons;
}
action_t action_context::has_action(mousebtn btn, int x) const {
// TODO optimize
return get_actions(x)[btn];
}
string action_context::get_action(action_t id) const {
assert(id >= 0 && (unsigned)id < num_actions());
return m_action_blocks[id].cmd;
}
bool action_context::has_double_click() const {
for (auto&& a : m_action_blocks) {
if (a.button == mousebtn::DOUBLE_LEFT || a.button == mousebtn::DOUBLE_MIDDLE ||
a.button == mousebtn::DOUBLE_RIGHT) {
return true;
}
}
return false;
}
size_t action_context::num_actions() const {
return m_action_blocks.size();
}
size_t action_context::num_unclosed() const {
size_t num = 0;
for (const auto& a : m_action_blocks) {
if (a.is_open) {
num++;
}
}
return num;
}
const std::vector<action_block>& action_context::get_blocks() const {
return m_action_blocks;
}
} // namespace tags
POLYBAR_NS_END

View File

@ -1,6 +1,7 @@
#include "tags/action_context.hpp"
#include "common/test.hpp"
#include "components/logger.hpp"
#include "tags/context.hpp"
using namespace polybar;
using namespace std;