diff options
| -rw-r--r-- | plugingui/layout.cc | 115 | ||||
| -rw-r--r-- | plugingui/layout.h | 60 | ||||
| -rw-r--r-- | plugingui/maintab.cc | 5 | ||||
| -rw-r--r-- | plugingui/maintab.h | 2 | 
4 files changed, 172 insertions, 10 deletions
| diff --git a/plugingui/layout.cc b/plugingui/layout.cc index 7e3c6e8..551611c 100644 --- a/plugingui/layout.cc +++ b/plugingui/layout.cc @@ -233,4 +233,119 @@ void HBoxLayout::setVAlignment(VAlignment alignment)  	align = alignment;  } +// +// GridLayout +// + +GridLayout::GridLayout(LayoutItem* parent, std::size_t number_of_columns, +    std::size_t number_of_rows) +    : BoxLayout(parent) +    , number_of_columns(number_of_columns) +    , number_of_rows(number_of_rows) +{ +} + +void GridLayout::removeItem(LayoutItem* item) +{ +	Layout::removeItem(item); + +	// manually remove from grid_ranges as remove_if doesn't work on an +	// unordered_map +	for(auto it = grid_ranges.begin(); it != grid_ranges.end(); ++it) +	{ +		if(it->first == item) +		{ +			it = grid_ranges.erase(it); +		} +		else +		{ +			++it; +		} +	} +} + +void GridLayout::layout() +{ +	if(grid_ranges.empty()) +	{ +		return; +	} + +	// Calculate cell sizes +	auto cell_size = calculateCellSize(); + +	for(auto const& pair : grid_ranges) +	{ +		auto& item = *pair.first; +		auto const& range = pair.second; + +		moveAndResize(item, range, cell_size); +	} +} + +void GridLayout::setPosition(LayoutItem* item, GridRange const& range) +{ +	grid_ranges[item] = range; +} + +auto GridLayout::calculateCellSize() const -> CellSize +{ +	auto empty_width = (number_of_columns - 1) * spacing; +	auto available_width = parent->width(); +	auto empty_height = (number_of_rows - 1) * spacing; +	auto available_height = parent->height(); + +	CellSize cell_size; +	if(available_width > empty_width && available_height > empty_height) +	{ +		cell_size.width = (available_width - empty_width) / number_of_columns; +		cell_size.height = (available_height - empty_height) / number_of_rows; +	} +	else +	{ +		cell_size.width = 0; +		cell_size.height = 0; +	} + +	return cell_size; +} + +void GridLayout::moveAndResize( +    LayoutItem& item, GridRange const& range, CellSize cell_size) const +{ +	std::size_t x = range.column_begin * (cell_size.width + spacing); +	std::size_t y = range.row_begin * (cell_size.height + spacing); + +	std::size_t column_count = (range.column_end - range.column_begin); +	std::size_t row_count = (range.row_end - range.row_begin); +	std::size_t width = column_count * (cell_size.width + spacing) - spacing; +	std::size_t height = row_count * (cell_size.height + spacing) - spacing; + +	if(resizeChildren) +	{ +		item.move(x, y); + +		if(cell_size.width * cell_size.height != 0) +		{ +			item.resize(width, height); +		} +		else +		{ +			item.resize(0, 0); +		} +	} +	else +	{ +		if(item.width() <= width && item.height() <= height) +		{ +			item.move(x + (width - item.width()) / 2, +			    y + (height - item.height()) / 2); +		} +		else +		{ +			item.move(x, y); +		} +	} +} +  } // GUI:: diff --git a/plugingui/layout.h b/plugingui/layout.h index 37a7d6d..763f616 100644 --- a/plugingui/layout.h +++ b/plugingui/layout.h @@ -28,6 +28,7 @@  #include <cstdlib>  #include <list> +#include <unordered_map>  #include <notifier.h> @@ -56,8 +57,7 @@ private:  };  //! \brief Abtract Layout class. -class Layout -	: public Listener +class Layout : public Listener  {  public:  	Layout(LayoutItem* parent); @@ -80,8 +80,7 @@ protected:  };  //! \brief Abstract box layout -class BoxLayout -	: public Layout +class BoxLayout : public Layout  {  public:  	BoxLayout(LayoutItem* parent); @@ -107,8 +106,7 @@ enum class HAlignment  };  //! \brief A Layout that lays out its elements vertically. -class VBoxLayout -	: public BoxLayout +class VBoxLayout : public BoxLayout  {  public:  	VBoxLayout(LayoutItem* parent); @@ -130,8 +128,7 @@ enum class VAlignment  };  //! \brief A Layout that lays out its elements vertically. -class HBoxLayout -	: public BoxLayout +class HBoxLayout : public BoxLayout  {  public:  	HBoxLayout(LayoutItem* parent); @@ -145,4 +142,51 @@ protected:  	VAlignment align;  }; +//! \brief A Layout class which places the items in a regular grid. An item can +//! span multiple rows/columns. +class GridLayout : public BoxLayout +{ +public: +	// The range is open, i.e. end is one past the last one. +	struct GridRange +	{ +		int column_begin; +		int column_end; +		int row_begin; +		int row_end; +	}; + +	GridLayout(LayoutItem* parent, std::size_t number_of_columns, +	    std::size_t number_of_rows); + +	virtual ~GridLayout() +	{ +	} + +	// From Layout: +	virtual void removeItem(LayoutItem* item); +	virtual void layout(); + +	void setPosition(LayoutItem* item, GridRange const& range); + +protected: +	std::size_t number_of_columns; +	std::size_t number_of_rows; + +	// Note: Yes, this is somewhat redundant to the LayoutItemList of the Layout +	// class. However, this was the best idea I had such that I could still +	// derive from Layout. If you find this ugly, feel free to fix it. +	std::unordered_map<LayoutItem*, GridRange> grid_ranges; + +private: +	struct CellSize { +		std::size_t width; +		std::size_t height; +	}; + +	CellSize calculateCellSize() const; +	void moveAndResize( +	    LayoutItem& item, GridRange const& range, CellSize cell_size) const; +}; +  } // GUI:: diff --git a/plugingui/maintab.cc b/plugingui/maintab.cc index f450bc0..498660e 100644 --- a/plugingui/maintab.cc +++ b/plugingui/maintab.cc @@ -33,12 +33,15 @@ MainTab::MainTab(Widget* parent) : Widget(parent)  {  	layout.setSpacing(10);  	layout.setResizeChildren(true); -	layout.setHAlignment(GUI::HAlignment::center);  	layout.addItem(&drumkit_frame);  	layout.addItem(&status_frame);  	layout.addItem(&humanizer_frame);  	layout.addItem(&diskstreaming_frame); +	layout.setPosition(&drumkit_frame, GridLayout::GridRange{0, 1, 0, 4}); +	layout.setPosition(&status_frame, GridLayout::GridRange{0, 1, 4, 7}); +	layout.setPosition(&humanizer_frame, GridLayout::GridRange{1, 2, 0, 3}); +	layout.setPosition(&diskstreaming_frame, GridLayout::GridRange{1, 2, 3, 5});  	drumkit_frame.setTitle("Drumkit");  	status_frame.setTitle("Status"); diff --git a/plugingui/maintab.h b/plugingui/maintab.h index 1ab30d7..ac39daf 100644 --- a/plugingui/maintab.h +++ b/plugingui/maintab.h @@ -42,7 +42,7 @@ public:  	MainTab(Widget* parent);  private: -	VBoxLayout layout{this}; +	GridLayout layout{this, 2, 9};  	FrameWidget drumkit_frame{this, false};  	FrameWidget status_frame{this, false}; | 
