[DEV] add a basic treeview (start dev)

This commit is contained in:
2018-08-24 23:56:19 +02:00
parent ebc0fdef72
commit 857ad3001b
11 changed files with 540 additions and 120 deletions

View File

@@ -0,0 +1,229 @@
/** @file
* @author Edouard DUPIN
* @copyright 2010, Edouard DUPIN, all right reserved
* @license GPL v3 (see license file)
*/
#include <appl/debug.hpp>
#include <appl/global.hpp>
#include <appl/widget/BufferList.hpp>
#include <appl/BufferManager.hpp>
//#include <ColorizeManager.hpp>
#include <appl/Gui/MainWindows.hpp>
#include <ewol/object/Object.hpp>
// TODO : write it better
static void SortElementList(etk::Vector<appl::dataBufferStruct>& _list) {
etk::Vector<appl::dataBufferStruct> tmpList = _list;
_list.clear();
for(size_t iii=0; iii<tmpList.size(); iii++) {
size_t findPos = 0;
for(size_t jjj=0; jjj<_list.size(); jjj++) {
//EWOL_DEBUG("compare : \""<<*tmpList[iii] << "\" and \"" << *m_listDirectory[jjj] << "\"");
if (tmpList[iii].m_bufferName.getNameFile() > _list[jjj].m_bufferName.getNameFile()) {
findPos = jjj+1;
}
}
//EWOL_DEBUG("position="<<findPos);
_list.insert(_list.begin()+findPos, tmpList[iii]);
}
}
appl::widget::BufferList::BufferList() :
m_openOrderMode(false) {
addObjectType("appl::BufferList");
m_selectedID = -1;
m_selectedIdRequested = -1;
// load buffer manager:
m_bufferManager = appl::BufferManager::create();
// load color properties
m_paintingProperties = appl::GlyphPainting::create("THEME:COLOR:bufferList.json");
// get all id properties ...
m_colorBackground1 = m_paintingProperties->request("backgroung1");
m_colorBackground2 = m_paintingProperties->request("backgroung2");
m_colorBackgroundSelect = m_paintingProperties->request("backgroungSelected");
m_colorTextNormal = m_paintingProperties->request("textNormal");
m_colorTextModify = m_paintingProperties->request("textModify");
}
void appl::widget::BufferList::init() {
ewol::widget::List::init();
propertyHide.set(true);
propertyCanFocus.set(true);
if (m_bufferManager != null) {
m_bufferManager->signalNewBuffer.connect(sharedFromThis(), &appl::widget::BufferList::onCallbackNewBuffer);
m_bufferManager->signalSelectFile.connect(sharedFromThis(), &appl::widget::BufferList::onCallbackselectNewFile);
m_bufferManager->signalRemoveBuffer.connect(sharedFromThis(), &appl::widget::BufferList::onCallbackBufferRemoved);
}
}
appl::widget::BufferList::~BufferList() {
removeAllElement();
}
void appl::widget::BufferList::calculateMinMaxSize() {
/*int32_t fontId = getDefaultFontId();
int32_t minWidth = ewol::getWidth(fontId, m_label);
int32_t minHeight = ewol::getHeight(fontId);
m_minSize.x = 3+minWidth;
m_minSize.y = 3+minHeight;
*/
m_minSize.setValue(300, 150);
}
void appl::widget::BufferList::removeAllElement() {
m_list.clear();
}
void appl::widget::BufferList::insertAlphabetic(const appl::dataBufferStruct& _dataStruct, bool _selectNewPosition) {
// alphabetical order:
for (size_t iii = 0; iii < m_list.size(); ++iii) {
if (m_list[iii].m_bufferName.getNameFile().toLower() > _dataStruct.m_bufferName.getNameFile().toLower()) {
m_list.insert(m_list.begin() + iii, _dataStruct);
if (_selectNewPosition == true) {
m_selectedID = iii;
}
return;
}
}
m_list.pushBack(_dataStruct);
if (_selectNewPosition == true) {
m_selectedID = m_list.size()-1;
}
}
void appl::widget::BufferList::onCallbackNewBuffer(const etk::String& _value) {
ememory::SharedPtr<appl::Buffer> buffer = m_bufferManager->get(_value);
if (buffer == null) {
APPL_ERROR("event on element nor exist : " << _value);
return;
}
buffer->signalIsSave.connect(sharedFromThis(), &BufferList::onCallbackIsSave);
buffer->signalIsModify.connect(sharedFromThis(), &BufferList::onCallbackIsModify);
buffer->signalChangeName.connect(sharedFromThis(), &BufferList::onCallbackChangeName);
appl::dataBufferStruct tmp(_value, buffer);
if (m_openOrderMode == true) {
m_list.pushBack(tmp);
} else {
insertAlphabetic(tmp);
}
if (m_list.size() <= 1) {
propertyHide.set(true);
propertySetOnWidgetNamed("appl-Buffer-viewer-separator", "hide", "true");
} else {
propertyHide.set(false);
propertySetOnWidgetNamed("appl-Buffer-viewer-separator", "hide", "false");
}
markToRedraw();
}
// TODO : Review this callback with the real shared_ptr on the buffer ...
void appl::widget::BufferList::onCallbackselectNewFile(const etk::String& _value) {
m_selectedID = -1;
for (size_t iii=0; iii<m_list.size(); iii++) {
if (m_list[iii].m_buffer == null) {
continue;
}
if (m_list[iii].m_buffer->getFileName() != _value) {
continue;
}
m_selectedID = iii;
break;
}
markToRedraw();
}
void appl::widget::BufferList::onCallbackChangeName() {
for (size_t iii = 0; iii < m_list.size(); ++iii) {
if (m_list[iii].m_bufferName != m_list[iii].m_buffer->getFileName()) {
m_list[iii].m_bufferName = m_list[iii].m_buffer->getFileName();
if (m_openOrderMode == false) {
// re-order the fine in the correct position
appl::dataBufferStruct tmp = m_list[iii];
m_list.erase(m_list.begin() + iii);
insertAlphabetic(tmp, ((int64_t)iii == m_selectedID));
break;
}
}
}
markToRedraw();
}
void appl::widget::BufferList::onCallbackBufferRemoved(const ememory::SharedPtr<appl::Buffer>& _buffer) {
APPL_ERROR("request remove buffer:");
auto it = m_list.begin();
while (it != m_list.end()) {
if (it->m_buffer == _buffer) {
it = m_list.erase(it);
m_selectedID = -1;
} else {
++it;
}
}
if (m_list.size() <= 1) {
propertyHide.set(true);
} else {
propertyHide.set(false);
}
markToRedraw();
}
void appl::widget::BufferList::onCallbackIsSave() {
markToRedraw();
}
void appl::widget::BufferList::onCallbackIsModify() {
markToRedraw();
}
etk::Color<> appl::widget::BufferList::getBasicBG() {
return (*m_paintingProperties)[m_colorBackground1].getForeground();
}
ivec2 appl::widget::BufferList::getMatrixSize() const {
return ivec2(1,m_list.size());
}
fluorine::Variant appl::widget::BufferList::getData(int32_t _role, const ivec2& _pos) {
switch (_role) {
case ewol::widget::ListRole::Text:
return m_list[_pos.y()].m_bufferName.getNameFile();;
case ewol::widget::ListRole::FgColor:
if ( m_list[_pos.y()].m_buffer != null
&& m_list[_pos.y()].m_buffer->isModify() == false) {
return (*m_paintingProperties)[m_colorTextNormal].getForeground();
} else {
return (*m_paintingProperties)[m_colorTextModify].getForeground();
}
case ewol::widget::ListRole::BgColor:
if (m_selectedID == _pos.y()) {
return (*m_paintingProperties)[m_colorBackgroundSelect].getForeground();
}
if (_pos.y() % 2) {
return (*m_paintingProperties)[m_colorBackground1].getForeground();
}
return (*m_paintingProperties)[m_colorBackground2].getForeground();
case ewol::widget::ListRole::IsSelected:
return m_selectedID == _pos.y();
}
return fluorine::Variant();
}
bool appl::widget::BufferList::onItemEvent(const ewol::event::Input& _event, const ivec2& _pos, const vec2& _mousePosition) {
if ( _event.getId() == 1
&& _event.getStatus() == gale::key::status::pressSingle) {
APPL_INFO("Event on List: " << _event << " pos=" << _pos );
if( _pos.y() >= 0
&& _pos.y() < (int64_t)m_list.size()) {
if (m_list[_pos.y()].m_buffer != null) {
if (m_bufferManager != null) {
APPL_INFO("Select file: '" << m_list[_pos.y()].m_buffer->getFileName() << "' in list");
m_bufferManager->open(m_list[_pos.y()].m_buffer->getFileName());
}
return true;
}
}
}
return false;
}

View File

@@ -0,0 +1,83 @@
/** @file
* @author Edouard DUPIN
* @copyright 2010, Edouard DUPIN, all right reserved
* @license GPL v3 (see license file)
*/
#pragma once
#include <appl/debug.hpp>
#include <appl/BufferManager.hpp>
#include <appl/globalMsg.hpp>
#include <ewol/widget/List.hpp>
#include <ewol/widget/Windows.hpp>
namespace appl {
class dataBufferStruct {
public:
etk::FSNode m_bufferName;
ememory::SharedPtr<appl::Buffer> m_buffer;
dataBufferStruct() {
};
dataBufferStruct(const etk::String& _bufferName, const ememory::SharedPtr<appl::Buffer>& _buffer) :
m_bufferName(_bufferName),
m_buffer(_buffer) {
};
virtual ~dataBufferStruct() { };
};
};
namespace appl {
namespace widget {
class BufferList;
using BufferListShared = ememory::SharedPtr<BufferList>;
using BufferListWeak = ememory::WeakPtr<BufferList>;
class BufferList : public ewol::widget::List {
private:
ememory::SharedPtr<appl::BufferManager> m_bufferManager; //!< handle on the buffer manager
private:
ememory::SharedPtr<appl::GlyphPainting> m_paintingProperties; //!< element painting property
int32_t m_colorBackground1;
int32_t m_colorBackground2;
int32_t m_colorBackgroundSelect;
int32_t m_colorTextNormal;
int32_t m_colorTextModify;
private:
int32_t m_selectedIdRequested;
int32_t m_selectedID;
etk::Vector<appl::dataBufferStruct> m_list;
/**
* @brief Insert the element in the alphabetic order.
* @param[in] _dataStruct element to add.
*/
void insertAlphabetic(const appl::dataBufferStruct& _dataStruct, bool _selectNewPosition = false);
protected:
// Constructeur
BufferList();
void init() override;
public:
DECLARE_FACTORY(BufferList);
virtual ~BufferList();
private:
bool m_openOrderMode; //!< true if the order is the opening order mode, otherwise, Alphabetic order
protected:
// function call to display the list :
etk::Color<> getBasicBG() override;
void removeAllElement();
// Derived function
ivec2 getMatrixSize() const override;
fluorine::Variant getData(int32_t _role, const ivec2& _pos) override;
bool onItemEvent(const ewol::event::Input& _event, const ivec2& _pos, const vec2& _mousePosition) override;
private: //callback function:
void onCallbackChangeName();
void onCallbackIsSave();
void onCallbackIsModify();
void onCallbackNewBuffer(const etk::String& _value);
void onCallbackselectNewFile(const etk::String& _value);
void onCallbackBufferRemoved(const ememory::SharedPtr<appl::Buffer>& _buffer);
void calculateMinMaxSize() override;
};
}
}

View File

@@ -0,0 +1,305 @@
/** @file
* @author Edouard DUPIN
* @copyright 2010, Edouard DUPIN, all right reserved
* @license GPL v3 (see license file)
*/
#include <appl/debug.hpp>
#include <appl/global.hpp>
#include <appl/widget/BufferTree.hpp>
#include <appl/BufferManager.hpp>
//#include <ColorizeManager.hpp>
#include <appl/Gui/MainWindows.hpp>
#include <ewol/object/Object.hpp>
// TODO : write it better
static void SortElementList(etk::Vector<appl::dataBufferStruct>& _list) {
etk::Vector<appl::dataBufferStruct> tmpList = _list;
_list.clear();
for(size_t iii=0; iii<tmpList.size(); iii++) {
size_t findPos = 0;
for(size_t jjj=0; jjj<_list.size(); jjj++) {
//EWOL_DEBUG("compare : \""<<*tmpList[iii] << "\" and \"" << *m_listDirectory[jjj] << "\"");
if (tmpList[iii].m_bufferName.getNameFile() > _list[jjj].m_bufferName.getNameFile()) {
findPos = jjj+1;
}
}
//EWOL_DEBUG("position="<<findPos);
_list.insert(_list.begin()+findPos, tmpList[iii]);
}
}
appl::widget::BufferTree::BufferTree() :
m_openOrderMode(false) {
addObjectType("appl::BufferTree");
m_selectedID = -1;
m_selectedIdRequested = -1;
// load buffer manager:
m_bufferManager = appl::BufferManager::create();
// load color properties
m_paintingProperties = appl::GlyphPainting::create("THEME:COLOR:BufferList.json");
// get all id properties ...
m_colorBackground1 = m_paintingProperties->request("backgroung1");
m_colorBackground2 = m_paintingProperties->request("backgroung2");
m_colorBackgroundSelect = m_paintingProperties->request("backgroungSelected");
m_colorTextNormal = m_paintingProperties->request("textNormal");
m_colorTextModify = m_paintingProperties->request("textModify");
}
void appl::widget::BufferTree::init() {
ewol::widget::TreeView::init();
//propertyHide.set(true);
propertyCanFocus.set(true);
if (m_bufferManager != null) {
m_bufferManager->signalNewBuffer2.connect(sharedFromThis(), &appl::widget::BufferTree::onNewBuffer);
m_bufferManager->signalSelectBuffer.connect(sharedFromThis(), &appl::widget::BufferTree::onSelectBuffer);
m_bufferManager->signalRemoveBuffer.connect(sharedFromThis(), &appl::widget::BufferTree::onRemoveBuffer);
}
}
static etk::String getCommonPathPart(const etk::String& _left, const etk::String& _right) {
etk::String out;
for (size_t iii=0; iii < etk::min(_left.size(), _right.size()); ++iii) {
if (_left[iii] == _right[iii]) {
out += _left[iii];
continue;
}
break;
}
return out;
}
void appl::widget::BufferTree::updateFlatTree() {
// Brut Force Mode...
etk::String upperParent = "";
etk::Vector<appl::BufferShared> tmpNewBuffer;
for (auto& it : *m_bufferManager) {
if (it == null) {
continue;
}
if (it->hasFileName() == false) {
tmpNewBuffer.pushBack(it);
continue;
}
etk::FSNode nodeName = it->getFileName();
if (upperParent == "") {
upperParent = nodeName.getNameFolder();
APPL_ERROR("init root: " << nodeName.getFileSystemName() << " root=" << upperParent);
continue;
}
upperParent = getCommonPathPart(upperParent, nodeName.getNameFolder());
APPL_ERROR("Update: " << nodeName.getFileSystemName() << " " << nodeName.getNameFolder() << " root=" << upperParent);
}
// Now we have the root path...
// Need to feed all elements needed
etk::FSNode nodeRoot = upperParent;
m_tree = etk::TreeNode<appl::TreeElement>::create(TreeElement(upperParent, true, true));
etk::Vector<etk::FSNode*> child = nodeRoot.folderGetSubList(false, true, true, false);
for (auto& it: child) {
APPL_WARNING("add element: " << *it);
if (it->getNodeType() == etk::typeNode_folder) {
auto elem = etk::TreeNode<appl::TreeElement>::create(TreeElement(it->getNameFile(), true, false));
m_tree->addChild(elem);
} else {
auto elem = etk::TreeNode<appl::TreeElement>::create(TreeElement(it->getNameFile(), false, false));
m_tree->addChild(elem);
}
// TODO: ETK_FREE(etk::FSNode, it);
}
m_flatTree.setRoot(m_tree,
[&](const TreeElement& _value){
return true;
},
[&](const TreeElement& _value){
return _value.m_isExpand;
});
markToRedraw();
}
appl::widget::BufferTree::~BufferTree() {
removeAllElement();
}
void appl::widget::BufferTree::calculateMinMaxSize() {
/*int32_t fontId = getDefaultFontId();
int32_t minWidth = ewol::getWidth(fontId, m_label);
int32_t minHeight = ewol::getHeight(fontId);
m_minSize.x = 3+minWidth;
m_minSize.y = 3+minHeight;
*/
m_minSize.setValue(300, 150);
}
void appl::widget::BufferTree::removeAllElement() {
//m_list.clear();
}
void appl::widget::BufferTree::onNewBuffer(const ememory::SharedPtr<appl::Buffer>& _buffer) {
updateFlatTree();
/*
ememory::SharedPtr<appl::Buffer> buffer = m_bufferManager->get(_value);
if (buffer == null) {
APPL_ERROR("event on element nor exist : " << _value);
return;
}
buffer->signalIsSave.connect(sharedFromThis(), &BufferTree::onCallbackIsSave);
buffer->signalIsModify.connect(sharedFromThis(), &BufferTree::onCallbackIsModify);
buffer->signalChangeName.connect(sharedFromThis(), &BufferTree::onCallbackChangeName);
appl::dataBufferStruct tmp(_value, buffer);
if (m_openOrderMode == true) {
m_list.pushBack(tmp);
} else {
insertAlphabetic(tmp);
}
if (m_list.size() <= 1) {
propertyHide.set(true);
propertySetOnWidgetNamed("appl-Buffer-viewer-separator", "hide", "true");
} else {
propertyHide.set(false);
propertySetOnWidgetNamed("appl-Buffer-viewer-separator", "hide", "false");
}
markToRedraw();
*/
}
void appl::widget::BufferTree::onSelectBuffer(const ememory::SharedPtr<appl::Buffer>& _buffer) {
#if 1
m_selection = _buffer;
updateFlatTree();
#else
auto elem = m_tree.findIf([&](const TreeNode<TreeElement>& _element) {
if (_element.getData().m_buffer == _buffer) {
return true;
}
return false;
});
for (auto& it: elem) {
_element.getData().m_isSelected = true;
// TODO: expand all this parents...
}
updateFlatTree();
#endif
}
void appl::widget::BufferTree::onCallbackChangeName() {
/*
for (size_t iii = 0; iii < m_list.size(); ++iii) {
if (m_list[iii].m_bufferName != m_list[iii].m_buffer->getFileName()) {
m_list[iii].m_bufferName = m_list[iii].m_buffer->getFileName();
if (m_openOrderMode == false) {
// re-order the fine in the correct position
appl::dataBufferStruct tmp = m_list[iii];
m_list.erase(m_list.begin() + iii);
insertAlphabetic(tmp, ((int64_t)iii == m_selectedID));
break;
}
}
}
*/
markToRedraw();
}
void appl::widget::BufferTree::onRemoveBuffer(const ememory::SharedPtr<appl::Buffer>& _buffer) {
APPL_ERROR("request remove buffer:");
auto elem = m_tree->findIf([&](const etk::TreeNode<TreeElement>& _element) {
if (_element.getData().m_buffer == _buffer) {
return true;
}
return false;
});
for (auto& it: elem) {
it->getData().m_isSelected = false;
it->getData().m_buffer = null;
}
markToRedraw();
}
void appl::widget::BufferTree::onCallbackIsSave() {
markToRedraw();
}
void appl::widget::BufferTree::onCallbackIsModify() {
markToRedraw();
}
etk::Color<> appl::widget::BufferTree::getBasicBG() {
return etk::Color<>(0xAF,0xAF,0xAF,0xFF);
return (*m_paintingProperties)[m_colorBackground1].getForeground();
}
ivec2 appl::widget::BufferTree::getMatrixSize() const {
return ivec2(1, m_flatTree.size());
}
fluorine::Variant appl::widget::BufferTree::getData(int32_t _role, const ivec2& _pos) {
auto elem = m_flatTree[_pos.y()];
appl::TreeElement& value = elem->getData();
switch (_role) {
case ewol::widget::ListRole::Text:
return value.m_nodeName;
case ewol::widget::ListRole::FgColor:
/*if ( m_list[_pos.y()].m_buffer != null
&& m_list[_pos.y()].m_buffer->isModify() == false) {
return (*m_paintingProperties)[m_colorTextNormal].getForeground();
} else {*/
return (*m_paintingProperties)[m_colorTextModify].getForeground();
//}
case ewol::widget::ListRole::BgColor:
return fluorine::Variant();
if (_pos.y() % 2) {
return (*m_paintingProperties)[m_colorBackground1].getForeground();
}
return (*m_paintingProperties)[m_colorBackground2].getForeground();
case ewol::widget::ListRole::Icon:
/*
if (elem->countToRoot() == 0) {
return "{ewol}THEME:GUI:Home.svg";
}*/
if (value.m_isFolder == true) {
return "{ewol}THEME:GUI:Folder.svg";
} else {
return "{ewol}THEME:GUI:File.svg";
}
return "";
case ewol::widget::ListRole::DistanceToRoot:
return uint_t(elem->countToRoot());
case ewol::widget::ListRole::HaveChild:
return elem->haveChild();
case ewol::widget::ListRole::IsExpand:
return value.m_isExpand;
case ewol::widget::ListRole::IsSelected:
return false;
}
return fluorine::Variant();
}
bool appl::widget::BufferTree::onItemEvent(const ewol::event::Input& _event, const ivec2& _pos, const vec2& _mousePosition) {
if (ewol::widget::TreeView::onItemEvent(_event, _pos, _mousePosition) == true) {
return true;
}
if ( _event.getId() == 1
&& _event.getStatus() == gale::key::status::pressSingle) {
APPL_INFO("Event on List: " << _event << " pos=" << _pos );
/*
if( _pos.y() >= 0
&& _pos.y() < (int64_t)m_list.size()) {
if (m_list[_pos.y()].m_buffer != null) {
if (m_bufferManager != null) {
APPL_INFO("Select file: '" << m_list[_pos.y()].m_buffer->getFileName() << "' in list");
m_bufferManager->open(m_list[_pos.y()].m_buffer->getFileName());
}
return true;
}
}
*/
}
return false;
}

View File

@@ -0,0 +1,82 @@
/** @file
* @author Edouard DUPIN
* @copyright 2010, Edouard DUPIN, all right reserved
* @license GPL v3 (see license file)
*/
#pragma once
#include <appl/debug.hpp>
#include <appl/BufferManager.hpp>
#include <appl/globalMsg.hpp>
#include <ewol/widget/TreeView.hpp>
#include <ewol/widget/Windows.hpp>
#include <etk/FlatTree.hpp>
namespace appl {
class TreeElement {
public:
TreeElement(const etk::String& _nodeName, bool _isFolder = false, bool _isExpand=false):
m_nodeName(_nodeName),
m_isFolder(_isFolder),
m_buffer(null),
m_isSelected(false),
m_isExpand(_isExpand) {
}
etk::String m_nodeName; // must be here ==> the buffer is optionnal..
bool m_isFolder;
ememory::SharedPtr<appl::Buffer> m_buffer;
bool m_isSelected = false;
bool m_isExpand = false;
};
namespace widget {
class BufferTree;
using BufferTreeShared = ememory::SharedPtr<BufferTree>;
using BufferTreeWeak = ememory::WeakPtr<BufferTree>;
class BufferTree : public ewol::widget::TreeView {
private:
ememory::SharedPtr<appl::BufferManager> m_bufferManager; //!< handle on the buffer manager
private:
ememory::SharedPtr<appl::GlyphPainting> m_paintingProperties; //!< element painting property
int32_t m_colorBackground1;
int32_t m_colorBackground2;
int32_t m_colorBackgroundSelect;
int32_t m_colorTextNormal;
int32_t m_colorTextModify;
private:
int32_t m_selectedIdRequested;
int32_t m_selectedID;
void updateFlatTree();
ememory::SharedPtr<etk::TreeNode<TreeElement>> m_tree;
etk::FlatTree<TreeElement> m_flatTree;
ememory::SharedPtr<appl::Buffer> m_selection;
protected:
// Constructeur
BufferTree();
void init() override;
public:
DECLARE_FACTORY(BufferTree);
virtual ~BufferTree();
private:
bool m_openOrderMode; //!< true if the order is the opening order mode, otherwise, Alphabetic order
protected:
// function call to display the list :
etk::Color<> getBasicBG() override;
void removeAllElement();
// Derived function
ivec2 getMatrixSize() const override;
fluorine::Variant getData(int32_t _role, const ivec2& _pos) override;
bool onItemEvent(const ewol::event::Input& _event, const ivec2& _pos, const vec2& _mousePosition) override;
private: //callback function:
void onCallbackChangeName();
void onCallbackIsSave();
void onCallbackIsModify();
void onNewBuffer(const ememory::SharedPtr<appl::Buffer>& _buffer);
void onSelectBuffer(const ememory::SharedPtr<appl::Buffer>& _buffer);
void onRemoveBuffer(const ememory::SharedPtr<appl::Buffer>& _buffer);
void calculateMinMaxSize() override;
};
}
}