Set up stacked widget.

This commit is contained in:
jmsgrogan 2020-06-27 10:47:30 +01:00
parent 4e85edacc8
commit ee51f3ee09
51 changed files with 808 additions and 195 deletions

View file

@ -1,10 +1,26 @@
list(APPEND client_LIB_INCLUDES GuiApplication.cpp TextEditorPanel.cpp)
list(APPEND client_LIB_INCLUDES
TopBar.cpp
StatusBar.cpp
GuiApplication.cpp
TabbedPanelWidget.cpp
text_editor/TextEditorView.cpp
text_editor/TextEditorModel.cpp
text_editor/TextEditorController.cpp
text_editor/PlainTextDocument.cpp
audio_editor/AudioEditorView.cpp
image_editor/ImageEditorView.cpp
web_client/WebClientView.cpp)
add_library(client SHARED ${client_LIB_INCLUDES})
target_link_libraries(client ui_elements windows core console database geometry)
target_include_directories(client PUBLIC
"${PROJECT_SOURCE_DIR}/src/console"
"${PROJECT_SOURCE_DIR}/src/ui_elements/widgets"
"${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/text_editor"
"${CMAKE_CURRENT_SOURCE_DIR}/audio_editor"
"${CMAKE_CURRENT_SOURCE_DIR}/image_editor"
"${CMAKE_CURRENT_SOURCE_DIR}/web_client"
"${PROJECT_SOURCE_DIR}/src/console"
"${PROJECT_SOURCE_DIR}/src/ui_elements/widgets"
)

View file

@ -1,18 +1,20 @@
#include "GuiApplication.h"
#include "Widget.h"
#include "HorizontalSpacer.h"
#include "VerticalSpacer.h"
#include "TextBox.h"
#include "Button.h"
#include "Label.h"
#include "XcbInterface.h"
#include "XcbKeyboard.h"
#include "Window.h"
#include "TextElement.h"
#include "WindowManager.h"
#include "TextEditorPanel.h"
#include <iostream>
#include "TextEditorView.h"
#include "AudioEditorView.h"
#include "ImageEditorView.h"
#include "WebClientView.h"
#include "TabbedPanelWidget.h"
#include "TopBar.h"
#include "StatusBar.h"
#include "HorizontalSpacer.h"
GuiApplication::GuiApplication()
: AbstractDesktopApp(),
@ -37,43 +39,34 @@ void GuiApplication::SetUpWidget()
auto mainWindow = mDesktopManager->GetWindowManager()->GetMainWindow();
mainWindow->SetSize(800, 600);
// Left panel
auto textEditorButton = Button::Create();
textEditorButton->SetLabel("Text Editor");
textEditorButton->SetBackgroundColor(Color::Create(156, 156, 156));
auto tabbedPanel = TabbedPanelWidget::Create();
auto imageEditorButton = Button::Create();
imageEditorButton->SetLabel("Image Editor");
imageEditorButton->SetBackgroundColor(Color::Create(156, 156, 156));
auto audioEditorButton = Button::Create();
audioEditorButton->SetLabel("Audio Editor");
audioEditorButton->SetBackgroundColor(Color::Create(156, 156, 156));
auto webClientButton = Button::Create();
webClientButton->SetLabel("Web Client");
webClientButton->SetBackgroundColor(Color::Create(156, 156, 156));
auto leftSpacer = HorizontalSpacer::Create();
leftSpacer->AddWidget(std::move(textEditorButton));
leftSpacer->AddWidget(std::move(imageEditorButton));
leftSpacer->AddWidget(std::move(audioEditorButton));
leftSpacer->AddWidget(std::move(webClientButton));
leftSpacer->SetMaxHeight(200);
// Right panel
auto textEditor = TextEditorPanel::Create();
textEditor->SetOnSaveFunction([](const std::string& content)
{
std::cout << content << std::endl;
});
auto textEditor = TextEditorView::Create();
auto path = mMainApplication->GetCommandLineArgs()->GetLaunchPath();
path /= "out.txt";
textEditor->GetController()->SetSavePath(path);
textEditor->GetController()->SetLoadPath(path);
textEditor->Initialize();
tabbedPanel->AddPanel(std::move(textEditor), "Text Editor");
auto vertSpacer = VerticalSpacer::Create();
vertSpacer->AddWidgetWithScale(std::move(leftSpacer), 1);
vertSpacer->AddWidgetWithScale(std::move(textEditor), 4);
auto audioEditor = AudioEditorView::Create();
tabbedPanel->AddPanel(std::move(audioEditor), "Audio Editor");
mainWindow->AddWidget(std::move(vertSpacer));
auto imageEditor = ImageEditorView::Create();
tabbedPanel->AddPanel(std::move(imageEditor), "Image Editor");
auto webClient = WebClientView::Create();
tabbedPanel->AddPanel(std::move(webClient), "Web Client");
auto topBar = TopBar::Create();
auto statusBar = StatusBar::Create();
auto horizontalSpace = HorizontalSpacer::Create();
horizontalSpace->AddWidgetWithScale(std::move(topBar), 1);
horizontalSpace->AddWidgetWithScale(std::move(tabbedPanel), 20);
horizontalSpace->AddWidgetWithScale(std::move(statusBar), 1);
mainWindow->AddWidget(std::move(horizontalSpace));
}
void GuiApplication::Run()

View file

View file

@ -0,0 +1,11 @@
#include "StatusBar.h"
StatusBar::StatusBar()
{
SetBackgroundColor(Color::Create(200, 200, 200));
}
std::unique_ptr<StatusBar> StatusBar::Create()
{
return std::make_unique<StatusBar>();
}

View file

@ -0,0 +1,14 @@
#pragma once
#include "Widget.h"
class StatusBar : public Widget
{
public:
StatusBar();
static std::unique_ptr<StatusBar> Create();
};
using StatusBarUPtr = std::unique_ptr<StatusBar>;

View file

@ -0,0 +1,52 @@
#include "TabbedPanelWidget.h"
#include "StackWidget.h"
#include "HorizontalSpacer.h"
#include "VerticalSpacer.h"
#include "Button.h"
TabbedPanelWidget::TabbedPanelWidget()
: mNavPanel(),
mStack()
{
auto stack = StackWidget::Create();
mStack = stack.get();
auto nav = HorizontalSpacer::Create();
mNavPanel = nav.get();
nav->SetSize({0, 0, 0, 0, 200, 0});
auto vertSpacer = VerticalSpacer::Create();
vertSpacer->AddWidgetWithScale(std::move(nav), 1);
vertSpacer->AddWidgetWithScale(std::move(stack), 4);
AddWidget(std::move(vertSpacer));
}
std::unique_ptr<TabbedPanelWidget> TabbedPanelWidget::Create()
{
return std::make_unique<TabbedPanelWidget>();
}
StackWidget* TabbedPanelWidget::GetStack() const
{
return mStack;
}
void TabbedPanelWidget::AddPanel(WidgetUPtr panel, const std::string& label)
{
auto button = Button::Create();
button->SetLabel(label);
button->SetBackgroundColor(Color::Create(156, 156, 156));
button->SetMargin({1, 0, 0, 1});
auto rawPanel = panel.get();
auto onClick = [this, rawPanel](Widget*){
if(this && rawPanel)
{
this->GetStack()->ShowChild(rawPanel);
}
};
button->SetOnClickFunction(onClick);
mStack->AddWidget(std::move(panel));
mNavPanel->AddWidget(std::move(button));
}

View file

@ -0,0 +1,22 @@
#pragma once
#include "Widget.h"
#include "StackWidget.h"
class TabbedPanelWidget : public Widget
{
Widget* mNavPanel;
StackWidget* mStack;
public:
TabbedPanelWidget();
static std::unique_ptr<TabbedPanelWidget> Create();
void AddPanel(WidgetUPtr panel, const std::string& label);
StackWidget* GetStack() const;
};
using TabbedPanelWidgetUPtr = std::unique_ptr<TabbedPanelWidget>;

View file

@ -1,59 +0,0 @@
#include "TextEditorPanel.h"
#include "HorizontalSpacer.h"
#include "VerticalSpacer.h"
TextEditorPanel::TextEditorPanel()
: mSaveFunction(),
mTextBox()
{
}
void TextEditorPanel::Initialize()
{
auto textEditorLabel = Label::Create();
textEditorLabel->SetLabel("Text Editor");
textEditorLabel->SetBackgroundColor(Color::Create(81, 89, 102));
auto textEditorBox = TextBox::Create();
mTextBox = textEditorBox.get();
auto textEditorSaveButton = Button::Create();
textEditorSaveButton->SetLabel("Save");
textEditorSaveButton->SetBackgroundColor(Color::Create(156, 156, 156));
if (mSaveFunction)
{
auto onSave = [this]()
{
if(this && mSaveFunction && mTextBox)
{
mSaveFunction(mTextBox->GetContent());
};
};
textEditorSaveButton->SetOnClickFunction(onSave);
}
auto textEditorClearButton = Button::Create();
textEditorClearButton->SetLabel("Clear");
textEditorClearButton->SetBackgroundColor(Color::Create(156, 156, 156));
auto buttonSpacer = VerticalSpacer::Create();
buttonSpacer->AddWidgetWithScale(std::move(textEditorSaveButton), 1);
buttonSpacer->AddWidgetWithScale(std::move(textEditorClearButton), 1);
auto hSpacer = HorizontalSpacer::Create();
hSpacer->AddWidgetWithScale(std::move(textEditorLabel), 1);
hSpacer->AddWidgetWithScale(std::move(textEditorBox), 8);
hSpacer->AddWidgetWithScale(std::move(buttonSpacer), 1);
AddWidget(std::move(hSpacer));
}
std::unique_ptr<TextEditorPanel> TextEditorPanel::Create()
{
return std::make_unique<TextEditorPanel>();
}
void TextEditorPanel::SetOnSaveFunction(saveFunc func)
{
mSaveFunction = func;
}

View file

@ -1,24 +0,0 @@
#pragma once
#include "Widget.h"
#include "Button.h"
#include "Label.h"
#include "TextBox.h"
class TextEditorPanel : public Widget
{
using saveFunc = void (*)(const std::string& content);
saveFunc mSaveFunction;
TextBox* mTextBox;
public:
TextEditorPanel();
static std::unique_ptr<TextEditorPanel> Create();
void Initialize();
void SetOnSaveFunction(saveFunc func);
};
using TextEditorPanelUPtr = std::unique_ptr<TextEditorPanel>;

View file

@ -0,0 +1,11 @@
#include "TopBar.h"
TopBar::TopBar()
{
SetBackgroundColor(Color::Create(50, 50, 50));
}
std::unique_ptr<TopBar> TopBar::Create()
{
return std::make_unique<TopBar>();
}

View file

@ -0,0 +1,14 @@
#pragma once
#include "Widget.h"
class TopBar : public Widget
{
public:
TopBar();
static std::unique_ptr<TopBar> Create();
};
using TopBarUPtr = std::unique_ptr<TopBar>;

View file

@ -0,0 +1,16 @@
#include "AudioEditorView.h"
#include "Label.h"
AudioEditorView::AudioEditorView()
{
auto label = Label::Create();
label->SetLabel("Audio Editor");
label->SetBackgroundColor(Color::Create(200, 189, 160));
label->SetMargin(1);
AddWidget(std::move(label));
}
std::unique_ptr<AudioEditorView> AudioEditorView::Create()
{
return std::make_unique<AudioEditorView>();
}

View file

@ -0,0 +1,14 @@
#pragma once
#include "Widget.h"
class AudioEditorView : public Widget
{
public:
AudioEditorView();
static std::unique_ptr<AudioEditorView> Create();
};
using AudioEditorViewUPtr = std::unique_ptr<AudioEditorView>;

View file

@ -0,0 +1,16 @@
#include "ImageEditorView.h"
#include "Label.h"
ImageEditorView::ImageEditorView()
{
auto label = Label::Create();
label->SetLabel("Image Editor");
label->SetBackgroundColor(Color::Create(200, 189, 160));
label->SetMargin(1);
AddWidget(std::move(label));
}
std::unique_ptr<ImageEditorView> ImageEditorView::Create()
{
return std::make_unique<ImageEditorView>();
}

View file

@ -0,0 +1,14 @@
#pragma once
#include "Widget.h"
class ImageEditorView : public Widget
{
public:
ImageEditorView();
static std::unique_ptr<ImageEditorView> Create();
};
using ImageEditorViewUPtr = std::unique_ptr<ImageEditorView>;

View file

@ -0,0 +1,27 @@
#include "PlainTextDocument.h"
PlainTextDocument::PlainTextDocument()
: mContent()
{
}
std::unique_ptr<PlainTextDocument> PlainTextDocument::Create()
{
return std::make_unique<PlainTextDocument>();
}
std::string PlainTextDocument::GetContent() const
{
return mContent;
}
void PlainTextDocument::SetContent(const std::string& content)
{
mContent = content;
}
void PlainTextDocument::Clear()
{
mContent = "";
}

View file

@ -0,0 +1,24 @@
#pragma once
#include <string>
#include <memory>
class PlainTextDocument
{
std::string mContent;
public:
PlainTextDocument();
static std::unique_ptr<PlainTextDocument> Create();
std::string GetContent() const;
void SetContent(const std::string& content);
void Clear();
};
using PlainTextDocumentUPtr = std::unique_ptr<PlainTextDocument>;

View file

@ -0,0 +1,60 @@
#include "TextEditorController.h"
#include "File.h"
TextEditorController::TextEditorController()
: mModel(TextEditorModel::Create()),
mSavePath(),
mLoadPath()
{
}
std::unique_ptr<TextEditorController> TextEditorController::Create()
{
return std::make_unique<TextEditorController>();
}
void TextEditorController::SetContent(const std::string& content)
{
mModel->GetDocument()->SetContent(content);
}
std::string TextEditorController::GetContent() const
{
return mModel->GetDocument()->GetContent();
}
void TextEditorController::OnSave()
{
if(mSavePath.empty()) return;
File outfile(mSavePath);
outfile.SetAccessMode(File::AccessMode::Write);
outfile.Open();
outfile.WriteText(mModel->GetDocument()->GetContent());
outfile.Close();
}
void TextEditorController::OnLoad()
{
if(mLoadPath.empty()) return;
File infile(mLoadPath);
infile.SetAccessMode(File::AccessMode::Read);
infile.Open();
mModel->GetDocument()->SetContent(infile.ReadText());
infile.Close();
}
void TextEditorController::SetSavePath(const std::filesystem::path& path)
{
mSavePath = path;
}
void TextEditorController::SetLoadPath(const std::filesystem::path& path)
{
mLoadPath = path;
}
void TextEditorController::OnClear()
{
mModel->GetDocument()->Clear();
}

View file

@ -0,0 +1,33 @@
#pragma once
#include <memory>
#include <filesystem>
#include "TextEditorModel.h"
class TextEditorController
{
TextEditorModelUPtr mModel;
std::filesystem::path mSavePath;
std::filesystem::path mLoadPath;
public:
TextEditorController();
static std::unique_ptr<TextEditorController> Create();
void OnSave();
void OnClear();
void OnLoad();
std::string GetContent() const;
void SetContent(const std::string& content);
void SetSavePath(const std::filesystem::path& path);
void SetLoadPath(const std::filesystem::path& path);
};
using TextEditorControllerUPtr = std::unique_ptr<TextEditorController>;

View file

@ -0,0 +1,17 @@
#include "TextEditorModel.h"
TextEditorModel::TextEditorModel()
: mDocument(PlainTextDocument::Create())
{
}
std::unique_ptr<TextEditorModel> TextEditorModel::Create()
{
return std::make_unique<TextEditorModel>();
}
PlainTextDocument* TextEditorModel::GetDocument() const
{
return mDocument.get();
}

View file

@ -0,0 +1,19 @@
#pragma once
#include "PlainTextDocument.h"
#include <memory>
class TextEditorModel
{
PlainTextDocumentUPtr mDocument;
public:
TextEditorModel();
static std::unique_ptr<TextEditorModel> Create();
PlainTextDocument* GetDocument() const;
};
using TextEditorModelUPtr = std::unique_ptr<TextEditorModel>;

View file

@ -0,0 +1,83 @@
#include "HorizontalSpacer.h"
#include "TextEditorView.h"
#include "VerticalSpacer.h"
#include <iostream>
TextEditorView::TextEditorView()
: mTextBox(),
mController(TextEditorController::Create())
{
}
TextEditorController* TextEditorView::GetController()
{
return mController.get();
}
void TextEditorView::Initialize()
{
auto label = Label::Create();
label->SetLabel("Text Editor");
label->SetBackgroundColor(Color::Create(181, 189, 200));
label->SetMargin(1);
auto textBox = TextBox::Create();
mTextBox = textBox.get();
auto saveButton = Button::Create();
saveButton->SetLabel("Save");
saveButton->SetBackgroundColor(Color::Create(200, 200, 200));
saveButton->SetMargin(2);
auto onSave = [this](Widget* self){
if(this && mController && mTextBox)
{
mController->SetContent(mTextBox->GetContent());
mController->OnSave();
};
};
saveButton->SetOnClickFunction(onSave);
auto clearButton = Button::Create();
clearButton->SetLabel("Clear");
clearButton->SetBackgroundColor(Color::Create(200, 200, 200));
clearButton->SetMargin(2);
auto onClear = [this](Widget* self){
if(this && mController && mTextBox)
{
mController->OnClear();
mTextBox->SetContent("");
};
};
clearButton->SetOnClickFunction(onClear);
auto loadButton = Button::Create();
loadButton->SetLabel("Load");
loadButton->SetBackgroundColor(Color::Create(200, 200, 200));
loadButton->SetMargin(2);
auto onLoad = [this](Widget* self){
if(this && mController && mTextBox)
{
mController->OnLoad();
mTextBox->SetContent(mController->GetContent());
};
};
loadButton->SetOnClickFunction(onLoad);
auto buttonSpacer = VerticalSpacer::Create();
buttonSpacer->AddWidgetWithScale(std::move(saveButton), 1);
buttonSpacer->AddWidgetWithScale(std::move(clearButton), 1);
buttonSpacer->AddWidgetWithScale(std::move(loadButton), 1);
auto hSpacer = HorizontalSpacer::Create();
hSpacer->AddWidgetWithScale(std::move(label), 1);
hSpacer->AddWidgetWithScale(std::move(textBox), 14);
hSpacer->AddWidgetWithScale(std::move(buttonSpacer), 1);
AddWidget(std::move(hSpacer));
}
std::unique_ptr<TextEditorView> TextEditorView::Create()
{
return std::make_unique<TextEditorView>();
}

View file

@ -0,0 +1,25 @@
#pragma once
#include "Widget.h"
#include "Button.h"
#include "Label.h"
#include "TextBox.h"
#include "TextEditorController.h"
#include <functional>
class TextEditorView : public Widget
{
TextBox* mTextBox;
TextEditorControllerUPtr mController;
public:
TextEditorView();
static std::unique_ptr<TextEditorView> Create();
TextEditorController* GetController();
void Initialize();
};
using TextEditorViewUPtr = std::unique_ptr<TextEditorView>;

View file

@ -0,0 +1,16 @@
#include "WebClientView.h"
#include "Label.h"
WebClientView::WebClientView()
{
auto label = Label::Create();
label->SetLabel("Web Client");
label->SetBackgroundColor(Color::Create(200, 189, 160));
label->SetMargin(1);
AddWidget(std::move(label));
}
std::unique_ptr<WebClientView> WebClientView::Create()
{
return std::make_unique<WebClientView>();
}

View file

@ -0,0 +1,14 @@
#pragma once
#include "Widget.h"
class WebClientView : public Widget
{
public:
WebClientView();
static std::unique_ptr<WebClientView> Create();
};
using WebClientViewUPtr = std::unique_ptr<WebClientView>;

View file

@ -98,6 +98,11 @@ void MainApplication::ConvertDocument(const std::string& inputPath, const std::s
converter.Convert(&input_file, &output_file);
}
CommandLineArgs* MainApplication::GetCommandLineArgs() const
{
return mCommandLineArgs.get();
}
void MainApplication::ShutDown()
{
mDatabaseManager->OnShutDown();

View file

@ -30,6 +30,8 @@ public:
void ShutDown();
CommandLineArgs* GetCommandLineArgs() const;
static std::shared_ptr<MainApplication> Create();
private:

View file

@ -1,5 +1,6 @@
#include "File.h"
#include "FileLogger.h"
#include <streambuf>
File::File(std::filesystem::path path)
: mFullPath(path),
@ -62,6 +63,18 @@ FileFormat::Format File::InferFormat() const
return FileFormat::InferFormat(extension);
}
void File::WriteText(const std::string& text)
{
(*mOutHandle) << text;
}
std::string File::ReadText()
{
std::string str((std::istreambuf_iterator<char>(*mInHandle)),
std::istreambuf_iterator<char>());
return str;
}
bool File::PathExists() const
{
return std::filesystem::exists(mFullPath);

View file

@ -32,6 +32,10 @@ public:
std::ofstream* GetOutHandle() const;
void WriteText(const std::string& text);
std::string ReadText();
bool PathExists() const;
void SetAccessMode(AccessMode mode);

View file

@ -11,6 +11,7 @@ list(APPEND ui_elements_LIB_INCLUDES
widgets/Label.cpp
widgets/HorizontalSpacer.cpp
widgets/VerticalSpacer.cpp
widgets/StackWidget.cpp
widgets/TextBox.cpp
widgets/elements/GeometryElement.cpp
widgets/elements/RectangleElement.cpp

View file

@ -37,7 +37,7 @@ void Window::OnKeyboardEvent(const KeyboardEvent* event)
void Window::OnPaint(const PaintEvent* event)
{
mLayers.clear();
mWidget->SetSize(mWidth, mHeight);
mWidget->SetBounds(mWidth, mHeight);
mWidget->OnPaintEvent(event);
auto layers = mWidget->GetLayers();

View file

@ -4,9 +4,10 @@
Button::Button()
: Widget(),
mLabel(),
mCachedColor(255, 255, 255),
mClickFunc()
{
mClickedColor = Color::Create(180, 180, 180);
}
std::unique_ptr<Button> Button::Create()
@ -28,15 +29,16 @@ void Button::OnMyMouseEvent(const MouseEvent* event)
{
if(event->GetAction() == MouseEvent::Action::Pressed)
{
SetBackgroundColor(Color::Create(0, 255, 0));
mCachedColor = *mBackgroundColor;
SetBackgroundColor(Color::Create(*mClickedColor));
if(mClickFunc)
{
mClickFunc();
mClickFunc(this);
}
}
else if(event->GetAction() == MouseEvent::Action::Released)
{
SetBackgroundColor(Color::Create(0, 255, 255));
SetBackgroundColor(Color::Create(mCachedColor));
}
}
@ -46,10 +48,13 @@ void Button::OnPaintEvent(const PaintEvent* event)
AddBackground(event);
if(!mLabel.empty())
{
auto middle = DiscretePoint(mLocation.GetX() + mWidth/2,
mLocation.GetY() + mHeight/2);
unsigned fontOffset = mLabel.size() * 4;
auto middle = DiscretePoint(mLocation.GetX() + mSize.mWidth/2 - fontOffset,
mLocation.GetY() + mSize.mHeight/2 + 4);
auto textLayer = VisualLayer::Create();
textLayer->SetText(TextElement::Create(mLabel, middle));
auto textElement = TextElement::Create(mLabel, middle);
textElement->SetFillColor(Color::Create(*mBackgroundColor));
textLayer->SetText(std::move(textElement));
mMyLayers.push_back(std::move(textLayer));
}
CopyMyLayers();

View file

@ -6,9 +6,11 @@
class Button : public Widget
{
private:
using clickFunc = std::function<void()>;
using clickFunc = std::function<void(Widget* self)>;
std::string mLabel;
clickFunc mClickFunc;
Color mCachedColor;
ColorUPtr mClickedColor;
public:
Button();

View file

@ -31,21 +31,22 @@ void HorizontalSpacer::AddChildLayers(const PaintEvent* event)
mLayers.clear();
double scaleSum = std::accumulate(mScales.begin(), mScales.end(), 0.0);
double offset = 0;
double height = mHeight;
if (mMaxHeight > 0 && height > mMaxHeight)
double height = mSize.mHeight;
if (mSize.mMaxHeight > 0 && height > mSize.mMaxHeight)
{
height = mMaxHeight;
height = mSize.mMaxHeight;
}
for(std::size_t idx=0; idx<mChildren.size(); idx++)
{
auto& child = mChildren[idx];
double scale = mScales[idx];
double delta = height * (scale/scaleSum);
if (child->GetMaxHeight() > 0 && delta > child->GetMaxHeight())
auto size = child->GetSize();
if (size.mMaxHeight > 0 && delta > size.mMaxHeight)
{
delta = child->GetMaxHeight();
delta = size.mMaxHeight;
}
child->SetSize(mWidth, delta);
child->SetBounds(mSize.mWidth, delta);
child->SetLocation(DiscretePoint(mLocation.GetX(), mLocation.GetY() + offset));
child->OnPaintEvent(event);
auto layers = child->GetLayers();

View file

@ -25,10 +25,13 @@ void Label::OnPaintEvent(const PaintEvent* event)
if(!mLabel.empty())
{
auto middle = DiscretePoint(mLocation.GetX() + mWidth/2,
mLocation.GetY() + mHeight/2);
unsigned fontOffset = mLabel.size() * 4;
auto middle = DiscretePoint(mLocation.GetX() + mSize.mWidth/2 - fontOffset,
mLocation.GetY() + mSize.mHeight/2 + 4);
auto textLayer = VisualLayer::Create();
textLayer->SetText(TextElement::Create(mLabel, middle));
auto textElement = TextElement::Create(mLabel, middle);
textElement->SetFillColor(Color::Create(*mBackgroundColor));
textLayer->SetText(std::move(textElement));
mMyLayers.push_back(std::move(textLayer));
}
CopyMyLayers();

View file

@ -0,0 +1,26 @@
#include "StackWidget.h"
StackWidget::StackWidget()
{
}
std::unique_ptr<StackWidget> StackWidget::Create()
{
return std::make_unique<StackWidget>();
}
void StackWidget::ShowChild(Widget* target)
{
for(auto& child : mChildren)
{
if(child.get() == target)
{
child->SetVisible(true);
}
else
{
child->SetVisible(false);
}
}
}

View file

@ -0,0 +1,15 @@
#pragma once
#include "Widget.h"
class StackWidget : public Widget
{
public:
StackWidget();
static std::unique_ptr<StackWidget> Create();
void ShowChild(Widget* child);
};
using StackWidgetUPtr = std::unique_ptr<StackWidget>;

View file

@ -8,7 +8,8 @@ TextBox::TextBox()
mContent(),
mCaps(false)
{
mBackgroundColor = Color::Create(240, 240, 220);
mBackgroundColor = Color::Create(250, 250, 250);
mPadding = {10, 0, 10, 0};
}
std::unique_ptr<TextBox> TextBox::Create()
@ -64,7 +65,6 @@ bool TextBox::OnMyKeyboardEvent(const KeyboardEvent* event)
AppendContent(keyString);
}
}
return true;
}
@ -85,12 +85,14 @@ void TextBox::OnPaintEvent(const PaintEvent* event)
}
for(const auto& line : seglist)
{
auto loc = DiscretePoint(mLocation.GetX() + mWidth/10,
mLocation.GetY() + mHeight/10 + offset);
auto loc = DiscretePoint(mLocation.GetX() + mPadding.mLeft,
mLocation.GetY() + mPadding.mTop + offset);
auto textLayer = VisualLayer::Create();
textLayer->SetText(TextElement::Create(line, loc));
auto textElement = TextElement::Create(line, loc);
textElement->SetFillColor(Color::Create(*mBackgroundColor));
textLayer->SetText(std::move(textElement));
mMyLayers.push_back(std::move(textLayer));
offset += 15;
offset += 20;
}
}
CopyMyLayers();

View file

@ -31,13 +31,13 @@ void VerticalSpacer::AddChildLayers(const PaintEvent* event)
mLayers.clear();
double scaleSum = std::accumulate(mScales.begin(), mScales.end(), 0.0);
double offset = 0;
unsigned delta = mWidth / mChildren.size();
unsigned delta = mSize.mWidth / mChildren.size();
for(std::size_t idx=0; idx<mChildren.size(); idx++)
{
auto& child = mChildren[idx];
double scale = mScales[idx];
double delta = mWidth * (scale/scaleSum);
child->SetSize(delta, mHeight);
double delta = mSize.mWidth * (scale/scaleSum);
child->SetBounds(delta, mSize.mHeight);
child->SetLocation(DiscretePoint(mLocation.GetX() + offset, mLocation.GetY()));
child->OnPaintEvent(event);
auto layers = child->GetLayers();

View file

@ -5,13 +5,16 @@
Widget::Widget()
: mLocation(DiscretePoint(0, 0)),
mWidth(100),
mHeight(100),
mMaxHeight(0),
mSize({100, 0, 0, 100, 0, 0}),
mPadding(),
mMargin(),
mMyLayers(),
mLayers(),
mChildren(),
mBackgroundColor(Color::Create(200, 0, 0))
mBorderThickness(0),
mBackgroundColor(Color::Create(255, 255, 255)),
mBorderColor(Color::Create(0, 0, 0)),
mVisible(true)
{
}
@ -31,14 +34,9 @@ void Widget::AddWidget(WidgetUPtr widget)
mChildren.push_back(std::move(widget));
}
unsigned Widget::GetWidth() const
Widget::BoundedSize Widget::GetSize() const
{
return mWidth;
}
unsigned Widget::GetHeight() const
{
return mHeight;
return mSize;
}
DiscretePoint Widget::GetLocation() const
@ -51,14 +49,29 @@ std::vector<VisualLayer*> Widget::GetLayers() const
return mLayers;
}
unsigned Widget::GetMaxHeight() const
void Widget::SetSize(const BoundedSize& size)
{
return mMaxHeight;
mSize = size;
}
void Widget::SetMaxHeight(unsigned maxHeight)
void Widget::SetMargin(unsigned margin)
{
mMaxHeight = maxHeight;
mMargin = {margin, margin, margin, margin};
}
void Widget::SetMargin(const BoundaryOffset& margin)
{
mMargin = margin;
}
void Widget::SetPadding(unsigned padding)
{
mPadding = {padding, padding, padding, padding};
}
void Widget::SetPadding(const BoundaryOffset& padding)
{
mPadding = padding;
}
void Widget::CopyMyLayers()
@ -69,11 +82,17 @@ void Widget::CopyMyLayers()
std::transform(mMyLayers.begin(), mMyLayers.end(), std::back_inserter(mLayers), getRaw);
}
void Widget::SetBounds(unsigned width, unsigned height)
{
mSize.mWidth = width;
mSize.mHeight = height;
}
void Widget::AddChildLayers(const PaintEvent* event)
{
for(auto& child: mChildren)
{
child->SetSize(mWidth, mHeight);
child->SetBounds(mSize.mWidth, mSize.mHeight);
child->SetLocation(mLocation);
child->OnPaintEvent(event);
const auto layers = child->GetLayers();
@ -84,6 +103,9 @@ void Widget::AddChildLayers(const PaintEvent* event)
void Widget::OnPaintEvent(const PaintEvent* event)
{
mMyLayers.clear();
mLayers.clear();
if(!mVisible)return;
AddBackground(event);
CopyMyLayers();
AddChildLayers(event);
@ -92,8 +114,8 @@ void Widget::OnPaintEvent(const PaintEvent* event)
bool Widget::Contains(const DiscretePoint& loc) const
{
if(loc.GetX() < mLocation.GetX()) return false;
if(loc.GetX() > mLocation.GetX() + mWidth) return false;
if(loc.GetY() > mLocation.GetY() + mHeight) return false;
if(loc.GetX() > mLocation.GetX() + mSize.mWidth) return false;
if(loc.GetY() > mLocation.GetY() + mSize.mHeight) return false;
if(loc.GetY() < mLocation.GetY()) return false;
return true;
}
@ -154,7 +176,12 @@ void Widget::OnMyMouseEvent(const MouseEvent* event)
void Widget::AddBackground(const PaintEvent* event)
{
auto shape = RectangleElement::Create(mLocation, mWidth, mHeight);
unsigned locX = mLocation.GetX() + mMargin.mLeft;
unsigned locY = mLocation.GetY() + mMargin.mTop;
unsigned deltaX = mSize.mWidth - mMargin.mLeft - mMargin.mRight;
unsigned deltaY = mSize.mHeight - mMargin.mTop - mMargin.mBottom;
auto shape = RectangleElement::Create(DiscretePoint(locX, locY),
deltaX, deltaY);
shape->SetFillColor(Color::Create(*mBackgroundColor));
auto shapeLayer = VisualLayer::Create();
shapeLayer->SetShape(std::move(shape));
@ -171,8 +198,7 @@ void Widget::SetLocation(const DiscretePoint& loc)
mLocation = loc;
}
void Widget::SetSize(unsigned width, unsigned height)
void Widget::SetVisible(bool visible)
{
mWidth = width;
mHeight = height;
mVisible = visible;
}

View file

@ -12,16 +12,35 @@
class Widget
{
protected:
public:
struct BoundaryOffset{
unsigned mLeft = 0;
unsigned mRight = 0;
unsigned mTop = 0;
unsigned mBottom = 0;
};
struct BoundedSize{
unsigned mWidth = 0;
unsigned mMaxWidth = 0;
unsigned mMinWidth = 0;
unsigned mHeight = 0;
unsigned mMaxHeight = 0;
unsigned mMinHeight = 0;
};
protected:
DiscretePoint mLocation;
unsigned mWidth;
unsigned mHeight;
unsigned mMaxHeight;
BoundedSize mSize;
BoundaryOffset mPadding;
BoundaryOffset mMargin;
std::vector<VisualLayerUPtr> mMyLayers;
std::vector<VisualLayer*> mLayers;
std::vector<std::unique_ptr<Widget> > mChildren;
unsigned mBorderThickness;
ColorUPtr mBackgroundColor;
ColorUPtr mBorderColor;
bool mVisible;
public:
@ -33,11 +52,7 @@ public:
virtual void AddWidget(std::unique_ptr<Widget> widget);
unsigned GetWidth() const;
unsigned GetHeight() const;
unsigned GetMaxHeight() const;
BoundedSize GetSize() const;
std::vector<VisualLayer*> GetLayers() const;
@ -53,11 +68,21 @@ public:
void SetBackgroundColor(ColorUPtr color);
void SetSize(unsigned mWidth, unsigned mHeight);
void SetBounds(unsigned width, unsigned height);
void SetSize(const BoundedSize& size);
void SetMargin(unsigned margin);
void SetMargin(const BoundaryOffset& margin);
void SetPadding(unsigned padding);
void SetPadding(const BoundaryOffset& padding);
void SetLocation(const DiscretePoint& loc);
void SetMaxHeight(unsigned maxHeight);
void SetVisible(bool visible);
protected:

View file

@ -3,7 +3,9 @@
TextElement::TextElement(const std::string& content, const DiscretePoint& loc)
: mContent(content),
mLocation(loc),
mFontLabel("7x14")
mFontLabel("7x14"),
mFillColor(Color::Create(255, 255, 255)),
mStrokeColor(Color::Create(0, 0, 0))
{
// https://en.wikipedia.org/wiki/Fixed_(typeface)#:~:text=misc%2Dfixed%20is%20a%20collection,to%20a%20single%20font%20family.
}
@ -18,6 +20,15 @@ std::unique_ptr<TextElement> TextElement::Create(const std::string& content, con
return std::make_unique<TextElement>(content, loc);
}
Color* TextElement::GetFillColor() const
{
return mFillColor.get();
}
Color* TextElement::GetStrokeColor() const
{
return mStrokeColor.get();
}
DiscretePoint TextElement::GetLocation() const
{
return mLocation;
@ -37,3 +48,13 @@ void TextElement::SetContent(const std::string& content)
{
mContent = content;
}
void TextElement::SetFillColor(ColorUPtr color)
{
mFillColor = std::move(color);
}
void TextElement::SetStrokeColor(ColorUPtr color)
{
mStrokeColor = std::move(color);
}

View file

@ -4,12 +4,15 @@
#include <string>
#include "DiscretePoint.h"
#include "Color.h"
class TextElement
{
std::string mContent;
DiscretePoint mLocation;
std::string mFontLabel;
ColorUPtr mFillColor;
ColorUPtr mStrokeColor;
public:
@ -19,13 +22,15 @@ public:
static std::unique_ptr<TextElement> Create(const std::string& content, const DiscretePoint& loc);
Color* GetFillColor() const;
Color* GetStrokeColor() const;
DiscretePoint GetLocation() const;
std::string GetContent() const;
std::string GetFontLabel() const;
void SetContent(const std::string& content);
void SetFillColor(ColorUPtr color);
void SetStrokeColor(ColorUPtr color);
};
using TextElementUPtr = std::unique_ptr<TextElement>;

View file

@ -71,7 +71,10 @@ void DesktopManager::OnUiEvent(UiEventUPtr eventUPtr)
OnMouseEvent(mouseEvent);
if(mouseEvent->GetAction() == MouseEvent::Action::Pressed)
{
std::cout << "mouse pressed" << std::endl;
mModified = true;
}
else if(mouseEvent->GetAction() == MouseEvent::Action::Released)
{
mModified = true;
}
break;

View file

@ -149,6 +149,7 @@ void XcbInterface::ShowWindow(mt::Window* window)
uint32_t XcbInterface::GetEventMask()
{
return XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS |
XCB_EVENT_MASK_BUTTON_RELEASE |
XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_POINTER_MOTION;
}
@ -226,6 +227,21 @@ void XcbInterface::OnButtonPress(xcb_button_press_event_t* event, DesktopManager
desktopManager->OnUiEvent(std::move(ui_event));
}
void XcbInterface::OnButtonRelease(xcb_button_release_event_t* event, DesktopManager* desktopManager)
{
auto ui_event = MouseEvent::Create();
auto x = static_cast<unsigned>(event->event_x);
auto y = static_cast<unsigned>(event->event_y);
ui_event->SetClientLocation(DiscretePoint(x, y));
auto screen_x = static_cast<unsigned>(event->root_x);
auto screen_y = static_cast<unsigned>(event->root_y);
ui_event->SetScreenLocation(DiscretePoint(x, y));
ui_event->SetAction(MouseEvent::Action::Released);
desktopManager->OnUiEvent(std::move(ui_event));
}
void XcbInterface::LoopOpenGl(DesktopManager* desktopManager)
{
int running = 1;
@ -311,7 +327,6 @@ void XcbInterface::Loop(DesktopManager* desktopManager)
OnKeyPress(kr, desktopManager);
break;
}
case XCB_KEY_RELEASE: {
auto kr = reinterpret_cast<xcb_key_release_event_t*>(event);
OnKeyRelease(kr, desktopManager);
@ -322,6 +337,11 @@ void XcbInterface::Loop(DesktopManager* desktopManager)
OnButtonPress(press, desktopManager);
break;
}
case XCB_BUTTON_RELEASE: {
auto release = reinterpret_cast<xcb_button_release_event_t*>(event);
OnButtonRelease(release, desktopManager);
break;
}
default:
/* Unknown event type, ignore it */
break;

View file

@ -76,6 +76,8 @@ private:
void OnButtonPress(xcb_button_press_event_t* event, DesktopManager*);
void OnButtonRelease(xcb_button_press_event_t* event, DesktopManager*);
void MapWindow(mt::Window* window);
void CreateGraphicsContext();

View file

@ -1,8 +1,10 @@
#include "XcbTextInterface.h"
#include "XcbLayerInterface.h"
#include <string.h>
xcb_gcontext_t XcbTextInterface::GetFontGC(xcb_connection_t *connection,
xcb_screen_t *screen, xcb_window_t window, const char*font_name)
xcb_screen_t *screen, xcb_window_t window, const char*font_name,
const TextElement* textElement)
{
/* get font */
xcb_font_t font = xcb_generate_id(connection);
@ -11,7 +13,8 @@ xcb_gcontext_t XcbTextInterface::GetFontGC(xcb_connection_t *connection,
/* create graphics context */
xcb_gcontext_t gc = xcb_generate_id(connection);
uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
uint32_t value_list[3] = {screen->black_pixel, screen->white_pixel, font };
auto fillColor = XcbLayerInterface::GetColor(textElement->GetFillColor());
uint32_t value_list[3] = {screen->black_pixel, fillColor, font };
xcb_create_gc(connection, gc, window, mask, value_list);
@ -26,7 +29,7 @@ void XcbTextInterface::AddTextElement(xcb_connection_t* connection,
{
/* get graphics context */
xcb_gcontext_t gc = XcbTextInterface::GetFontGC(connection, screen, window,
textElement->GetFontLabel().c_str());
textElement->GetFontLabel().c_str(), textElement);
/* draw the text */
std::string content = textElement->GetContent();

View file

@ -6,7 +6,8 @@ class XcbTextInterface
{
public:
static xcb_gcontext_t GetFontGC(xcb_connection_t* connection,
xcb_screen_t*screen, xcb_window_t window, const char*font_name);
xcb_screen_t*screen, xcb_window_t window, const char*font_name,
const TextElement* textElement);
static void AddTextElement(xcb_connection_t* connection,
xcb_screen_t* screen, xcb_window_t window,