Simple menu
parent
2a4c0af69a
commit
0f0e37e02d
|
@ -34,6 +34,8 @@ set(SOURCES
|
|||
main.cc
|
||||
mainwindow.cc
|
||||
mainwindow.h
|
||||
menu.cc
|
||||
menu.h
|
||||
md-parser.cc
|
||||
md-parser.h
|
||||
render-area.cc
|
||||
|
|
|
@ -4,10 +4,8 @@
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
|
||||
auto app = Gtk::Application::create(argc, argv, "org.melroy.browser");
|
||||
|
||||
MainWindow window;
|
||||
|
||||
//Shows the window and returns when it is closed.
|
||||
return app->run(window);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <gtkmm/menuitem.h>
|
||||
#ifdef LEGACY_CXX
|
||||
#include <experimental/filesystem>
|
||||
namespace n_fs = ::std::experimental::filesystem;
|
||||
|
@ -11,17 +12,22 @@ namespace n_fs = ::std::experimental::filesystem;
|
|||
namespace n_fs = ::std::filesystem;
|
||||
#endif
|
||||
|
||||
MainWindow::MainWindow()
|
||||
MainWindow::MainWindow() : m_vbox(Gtk::ORIENTATION_VERTICAL, 0)
|
||||
{
|
||||
set_title("Browser");
|
||||
set_default_size(1000, 800);
|
||||
set_position(Gtk::WIN_POS_CENTER_ALWAYS);
|
||||
|
||||
add(m_scrolledWindow);
|
||||
// Connect signals
|
||||
m_menu.quit.connect(sigc::mem_fun(this, &MainWindow::hide)); /*!< hide main window and therefor closes the app */
|
||||
|
||||
m_vbox.pack_start(m_menu, false, false, 0);
|
||||
|
||||
m_scrolledWindow.add(m_renderArea);
|
||||
m_scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
|
||||
|
||||
|
||||
m_vbox.pack_end(m_scrolledWindow, true, true, 0);
|
||||
add(m_vbox);
|
||||
show_all_children();
|
||||
|
||||
// Setup parser
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
#define MAINWINDOW_H
|
||||
|
||||
#include <gtkmm/window.h>
|
||||
#include <gtkmm/box.h>
|
||||
#include <gtkmm/menubar.h>
|
||||
#include <gtkmm/scrolledwindow.h>
|
||||
#include "render-area.h"
|
||||
#include "menu.h"
|
||||
|
||||
class Parser;
|
||||
|
||||
|
@ -19,6 +22,8 @@ protected:
|
|||
void on_button_clicked(Glib::ustring data);
|
||||
|
||||
// Child widgets
|
||||
Menu m_menu;
|
||||
Gtk::Box m_vbox;
|
||||
Gtk::ScrolledWindow m_scrolledWindow;
|
||||
RenderArea m_renderArea;
|
||||
private:
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
#include "menu.h"
|
||||
|
||||
Menu::Menu()
|
||||
: m_file("_File", true),
|
||||
m_view("_View", true),
|
||||
m_help("_Help", true)
|
||||
{
|
||||
// File submenu
|
||||
auto exit_menuitem = createMenuItem("Exit");
|
||||
exit_menuitem->signal_activate().connect(quit);
|
||||
|
||||
// View submenu
|
||||
auto source_code_menuitem = createMenuItem("View source");
|
||||
source_code_menuitem->signal_activate().connect(source_code);
|
||||
|
||||
// Help submenu
|
||||
auto about_menuitem = createMenuItem("About");
|
||||
about_menuitem->signal_activate().connect(show_about);
|
||||
|
||||
// Add items to sub-menus
|
||||
m_file_submenu.append(*exit_menuitem);
|
||||
m_view_submenu.append(*source_code_menuitem);
|
||||
m_help_submenu.append(*about_menuitem);
|
||||
|
||||
// Add sub-menus to menus
|
||||
m_file.set_submenu(m_file_submenu);
|
||||
m_view.set_submenu(m_view_submenu);
|
||||
m_help.set_submenu(m_help_submenu);
|
||||
// Add menus to menu bar
|
||||
append(m_file);
|
||||
append(m_view);
|
||||
append(m_help);
|
||||
}
|
||||
|
||||
Menu::~Menu() {
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Helper method for creating a menu with an image
|
||||
* \return GTKWidget menu item pointer
|
||||
*/
|
||||
Gtk::MenuItem* Menu::createMenuItem(const Glib::ustring& label_text) {
|
||||
Gtk::MenuItem* item = Gtk::manage(new Gtk::MenuItem(label_text));
|
||||
return item;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#include <signal.h>
|
||||
#include <gtkmm/menubar.h>
|
||||
#include <gtkmm/menu.h>
|
||||
#include <gtkmm/menuitem.h>
|
||||
#include <gtkmm/separatormenuitem.h>
|
||||
|
||||
/**
|
||||
* \class Menu
|
||||
* \brief The top main-menu
|
||||
*/
|
||||
class Menu: public Gtk::MenuBar
|
||||
{
|
||||
public:
|
||||
sigc::signal<void> source_code;
|
||||
sigc::signal<void> quit;
|
||||
sigc::signal<void> show_about;
|
||||
|
||||
Menu();
|
||||
virtual ~Menu();
|
||||
Gtk::Menu* GetMachineMenu();
|
||||
|
||||
protected:
|
||||
// Child widgets
|
||||
Gtk::MenuItem m_file;
|
||||
Gtk::MenuItem m_view;
|
||||
Gtk::MenuItem m_help;
|
||||
Gtk::Menu m_file_submenu; /*!< File sub menu */
|
||||
Gtk::Menu m_view_submenu; /*!< Help sub menu */
|
||||
Gtk::Menu m_help_submenu; /*!< Help sub menu */
|
||||
Gtk::SeparatorMenuItem m_separator1;
|
||||
|
||||
private:
|
||||
Gtk::MenuItem* createMenuItem(const Glib::ustring& label_text);
|
||||
};
|
|
@ -1,278 +0,0 @@
|
|||
#include "qt-renderer.h"
|
||||
#include "scene.h"
|
||||
#include "cmark-gfm.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
#include <node.h>
|
||||
#include <QFont>
|
||||
#include <QGraphicsTextItem>
|
||||
#include <QGraphicsRectItem>
|
||||
#include <QGraphicsSimpleTextItem>
|
||||
#include <QPainter>
|
||||
|
||||
QtRenderer::QtRenderer():
|
||||
scene(NULL),
|
||||
defaultFontSize(12),
|
||||
sceneMarginX(3.0),
|
||||
sceneMarginY(3.0),
|
||||
bold(false),
|
||||
italic(false),
|
||||
headingLevel(0),
|
||||
listLevel(0),
|
||||
currentX(0.0),
|
||||
currentY(0.0),
|
||||
fontFamilty("Open Sans"),
|
||||
wordSpacing(4.0), // spacing may depend on the font
|
||||
heighestHigh(0.0),
|
||||
paragraphHeightOffset(5.0),
|
||||
headingHeightOffset(10.0),
|
||||
listXOffset(15.0),
|
||||
bulletWithTemp(0.0) {
|
||||
font = new QFont();
|
||||
font->setPixelSize(defaultFontSize);
|
||||
font->setFamily(fontFamilty);
|
||||
}
|
||||
|
||||
QtRenderer::~QtRenderer()
|
||||
{
|
||||
delete font;
|
||||
}
|
||||
|
||||
void QtRenderer::setScene(Scene* scene)
|
||||
{
|
||||
this->scene = scene;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the whole document to scene/screen
|
||||
*/
|
||||
void QtRenderer::renderDocument(cmark_node *root, int width)
|
||||
{
|
||||
cmark_event_type ev_type;
|
||||
cmark_iter *iter = cmark_iter_new(root);
|
||||
while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
|
||||
cmark_node *cur = cmark_iter_get_node(iter);
|
||||
renderNode(cur, ev_type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the locations, render and paint the content/objects
|
||||
* to a QGraphicsScene
|
||||
*/
|
||||
void QtRenderer::renderNode(cmark_node *node, cmark_event_type ev_type)
|
||||
{
|
||||
bool entering = (ev_type == CMARK_EVENT_ENTER);
|
||||
|
||||
switch (node->type) {
|
||||
case CMARK_NODE_DOCUMENT:
|
||||
if (entering) {
|
||||
currentX = sceneMarginX;
|
||||
currentY = sceneMarginY;
|
||||
}
|
||||
break;
|
||||
|
||||
case CMARK_NODE_BLOCK_QUOTE:
|
||||
break;
|
||||
|
||||
case CMARK_NODE_LIST:
|
||||
if (entering) {
|
||||
listLevel++;
|
||||
} else {
|
||||
listLevel--;
|
||||
if (listLevel < 0)
|
||||
listLevel = 0;
|
||||
}
|
||||
|
||||
if (listLevel == 0) {
|
||||
// Reset X to be safe
|
||||
currentX = sceneMarginX;
|
||||
} else if (listLevel > 0) {
|
||||
if (entering) {
|
||||
currentX += listXOffset;
|
||||
} else {
|
||||
currentX -= listXOffset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CMARK_NODE_ITEM:
|
||||
// Line break for list items
|
||||
currentY += heighestHigh;
|
||||
// Reset heighest high (Y-axis)
|
||||
heighestHigh = 0;
|
||||
|
||||
// Add bullet before text items
|
||||
if (entering) {
|
||||
const QRectF rec = drawBullet();
|
||||
bulletWithTemp = rec.width() + 2.0; // + offset
|
||||
currentX += bulletWithTemp;
|
||||
} else {
|
||||
currentX -= bulletWithTemp;
|
||||
}
|
||||
break;
|
||||
|
||||
case CMARK_NODE_HEADING:
|
||||
if (entering) {
|
||||
headingLevel = node->as.heading.level;
|
||||
} else {
|
||||
headingLevel = 0; // reset
|
||||
}
|
||||
// Move to left again
|
||||
currentX = sceneMarginX;
|
||||
// New heading
|
||||
currentY += heighestHigh + headingHeightOffset;
|
||||
|
||||
// Reset heighest high (Y-axis)
|
||||
heighestHigh = 0;
|
||||
|
||||
break;
|
||||
|
||||
case CMARK_NODE_CODE_BLOCK:
|
||||
break;
|
||||
|
||||
case CMARK_NODE_HTML_BLOCK:
|
||||
break;
|
||||
|
||||
case CMARK_NODE_CUSTOM_BLOCK:
|
||||
break;
|
||||
|
||||
case CMARK_NODE_THEMATIC_BREAK:
|
||||
break;
|
||||
|
||||
case CMARK_NODE_PARAGRAPH:
|
||||
// Skip paragraph if listing is enabled
|
||||
if (listLevel == 0) {
|
||||
// Move to left again
|
||||
currentX = sceneMarginX;
|
||||
// New paragraph
|
||||
currentY += heighestHigh + paragraphHeightOffset;
|
||||
|
||||
// Reset heighest high (Y-axis)
|
||||
heighestHigh = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case CMARK_NODE_TEXT: {
|
||||
const QRectF rec = drawText(cmark_node_get_literal(node));
|
||||
// Skip paragraph if listing is enabled
|
||||
if (listLevel == 0) {
|
||||
currentX += rec.width();
|
||||
}
|
||||
if (rec.height() > heighestHigh)
|
||||
heighestHigh = rec.height();
|
||||
}
|
||||
break;
|
||||
|
||||
case CMARK_NODE_LINEBREAK:
|
||||
// Move to left again
|
||||
currentX = sceneMarginX;
|
||||
// Line break (no soft break)
|
||||
currentY += heighestHigh;
|
||||
|
||||
// Reset heighest high (Y-axis)
|
||||
heighestHigh = 0;
|
||||
break;
|
||||
|
||||
case CMARK_NODE_SOFTBREAK:
|
||||
// ignore
|
||||
// Only insert a space between the words
|
||||
currentX += wordSpacing;
|
||||
break;
|
||||
|
||||
case CMARK_NODE_CODE:
|
||||
break;
|
||||
|
||||
case CMARK_NODE_HTML_INLINE:
|
||||
break;
|
||||
|
||||
case CMARK_NODE_CUSTOM_INLINE:
|
||||
break;
|
||||
|
||||
case CMARK_NODE_STRONG:
|
||||
bold = entering;
|
||||
break;
|
||||
|
||||
case CMARK_NODE_EMPH:
|
||||
italic = entering;
|
||||
break;
|
||||
|
||||
case CMARK_NODE_LINK:
|
||||
break;
|
||||
|
||||
case CMARK_NODE_IMAGE:
|
||||
break;
|
||||
|
||||
case CMARK_NODE_FOOTNOTE_REFERENCE:
|
||||
break;
|
||||
|
||||
case CMARK_NODE_FOOTNOTE_DEFINITION:
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QRectF const QtRenderer::drawText(const QString& text)
|
||||
{
|
||||
typedef std::chrono::high_resolution_clock Time;
|
||||
typedef std::chrono::milliseconds ms;
|
||||
typedef std::chrono::duration<float> fsec;
|
||||
auto t0 = Time::now();
|
||||
|
||||
// We can still extend the QGraphicsSimpleTextItem class (or QAbstractGraphicsShapeItem) and override paint method.
|
||||
// Or just use QPainter with a paint device (like QWidgets), to have maximal control.
|
||||
QGraphicsSimpleTextItem *textItem = new QGraphicsSimpleTextItem(text);
|
||||
font->setBold(bold);
|
||||
font->setItalic(italic);
|
||||
|
||||
if (headingLevel > 0) {
|
||||
font->setBold(true);
|
||||
switch(headingLevel) {
|
||||
case 1:
|
||||
font->setPixelSize(24);
|
||||
break;
|
||||
case 2:
|
||||
font->setPixelSize(20);
|
||||
break;
|
||||
case 3:
|
||||
font->setPixelSize(16);
|
||||
break;
|
||||
case 4:
|
||||
font->setPixelSize(14);
|
||||
break;
|
||||
case 5:
|
||||
font->setPixelSize(12);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
textItem->setFont(*font);
|
||||
textItem->setPos(currentX, currentY);
|
||||
scene->addItem(textItem);
|
||||
|
||||
if (headingLevel > 0) {
|
||||
font->setPixelSize(defaultFontSize);
|
||||
}
|
||||
|
||||
auto t1 = Time::now();
|
||||
fsec fs = t1 - t0;
|
||||
ms d = std::chrono::duration_cast<ms>(fs);
|
||||
std::cout << "Draw Text: " << d.count() << " ms . Content: " << text.toStdString().c_str() << std::endl;
|
||||
|
||||
return textItem->boundingRect();
|
||||
}
|
||||
|
||||
QRectF const QtRenderer::drawBullet()
|
||||
{
|
||||
QGraphicsSimpleTextItem *bullet = new QGraphicsSimpleTextItem("\u2022");
|
||||
bullet->setFont(*font);
|
||||
bullet->setPos(currentX, currentY);
|
||||
scene->addItem(bullet);
|
||||
return bullet->boundingRect();
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
#ifndef QT_RENDER_H
|
||||
#define QT_RENDER_H
|
||||
|
||||
#include <cmark-gfm.h>
|
||||
#include <render.h>
|
||||
#include <QtGlobal>
|
||||
#include <QString>
|
||||
#include "renderer-interface.h"
|
||||
|
||||
class Scene;
|
||||
class QRectF;
|
||||
class QFont;
|
||||
|
||||
/**
|
||||
* \class QtRenderer Class will use Qt to render AST object to a QGraphicsScene
|
||||
*/
|
||||
class QtRenderer : public RendererI
|
||||
{
|
||||
public:
|
||||
explicit QtRenderer();
|
||||
~QtRenderer();
|
||||
|
||||
void setScene(Scene *scene) override;
|
||||
void setUnknownYet() override {}; // No implementation
|
||||
void renderDocument(cmark_node *root, int width = 0) override;
|
||||
|
||||
private:
|
||||
Scene *scene;
|
||||
QFont *font;
|
||||
int defaultFontSize;
|
||||
qreal sceneMarginX;
|
||||
qreal sceneMarginY;
|
||||
bool bold;
|
||||
bool italic;
|
||||
int headingLevel;
|
||||
int listLevel;
|
||||
qreal currentX;
|
||||
qreal currentY;
|
||||
QString fontFamilty;
|
||||
qreal wordSpacing;
|
||||
qreal heighestHigh;
|
||||
qreal paragraphHeightOffset;
|
||||
qreal headingHeightOffset;
|
||||
qreal listXOffset;
|
||||
qreal bulletWithTemp;
|
||||
|
||||
// Copy contructor (not used/non-copyable)
|
||||
QtRenderer(const QtRenderer& _);
|
||||
// Copy assignment (not used/not assignable)
|
||||
QtRenderer& operator=(const QtRenderer& _);
|
||||
|
||||
void renderNode(cmark_node *node, cmark_event_type ev_type);
|
||||
QRectF const drawText(const QString& text);
|
||||
QRectF const drawBullet();
|
||||
};
|
||||
#endif
|
|
@ -1,3 +1,2 @@
|
|||
missingIncludeSystem
|
||||
missingInclude:lib/*
|
||||
unusedFunction:src/*
|
||||
|
|
Loading…
Reference in New Issue