diff options
author | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-06-28 13:04:50 +0200 |
---|---|---|
committer | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-06-28 13:04:50 +0200 |
commit | 22bf928025e0b289cb18b3624081055f96e645c9 (patch) | |
tree | 2d591b52566dea91703d4ae1f92fc614ce141480 | |
parent | edabdffead6d33a4e6a0e5a84d9e15f25a6acf83 (diff) | |
download | qtmips-22bf928025e0b289cb18b3624081055f96e645c9.tar.gz qtmips-22bf928025e0b289cb18b3624081055f96e645c9.tar.bz2 qtmips-22bf928025e0b289cb18b3624081055f96e645c9.zip |
LCD display emulation updated to keep aspect ratio.
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
-rw-r--r-- | qtmips_gui/lcddisplaydock.cpp | 49 | ||||
-rw-r--r-- | qtmips_gui/lcddisplaydock.h | 8 | ||||
-rw-r--r-- | qtmips_gui/lcddisplayview.cpp | 65 | ||||
-rw-r--r-- | qtmips_gui/lcddisplayview.h | 8 |
4 files changed, 117 insertions, 13 deletions
diff --git a/qtmips_gui/lcddisplaydock.cpp b/qtmips_gui/lcddisplaydock.cpp index 6517f4a..1109efd 100644 --- a/qtmips_gui/lcddisplaydock.cpp +++ b/qtmips_gui/lcddisplaydock.cpp @@ -40,9 +40,17 @@ #include "lcddisplaydock.h" #include "lcddisplayview.h" -LcdDisplayDock::LcdDisplayDock(QWidget *parent, QSettings *settings) : QDockWidget(parent) { +LcdDisplayDock::LcdDisplayDock(QWidget *parent, QSettings *settings) : Super(parent) { lcd_display_widget = new LcdDisplayView(this); - setWidget(lcd_display_widget); + QWidget *fill_widget = new QWidget(this); + + layout = new QBoxLayout(QBoxLayout::LeftToRight, fill_widget); + // add spacer, then your widget, then spacer + layout->addItem(new QSpacerItem(0, 0)); + layout->addWidget(lcd_display_widget); + layout->addItem(new QSpacerItem(0, 0)); + fill_widget->setLayout(layout); + setWidget(fill_widget); setObjectName("LCD Display"); setWindowTitle("LCD Display"); @@ -54,4 +62,41 @@ LcdDisplayDock::~LcdDisplayDock() { void LcdDisplayDock::setup(machine::LcdDisplay *lcd_display) { lcd_display_widget->setup(lcd_display); + update_layout(width(), height()); +} + +void LcdDisplayDock::update_layout(int w, int h) { + // Keeping aspect ratio based on + // https://stackoverflow.com/questions/30005540/keeping-the-aspect-ratio-of-a-sub-classed-qwidget-during-resize + + float thisAspectRatio = (float)w / h; + int widgetStretch, outerStretch; + float arWidth = lcd_display_widget->fb_width(); // aspect ratio width + float arHeight = lcd_display_widget->fb_height(); // aspect ratio height + + if ((arWidth == 0) || (arHeight == 0)) { + outerStretch = 0; + widgetStretch = 1; + } else if (thisAspectRatio > (arWidth/arHeight)) { // too wide + layout->setDirection(QBoxLayout::LeftToRight); + widgetStretch = height() * (arWidth/arHeight); // i.e., my width + outerStretch = (width() - widgetStretch) / 2 + 0.5; + } else { // too tall + layout->setDirection(QBoxLayout::TopToBottom); + widgetStretch = width() * (arHeight/arWidth); // i.e., my height + outerStretch = (height() - widgetStretch) / 2 + 0.5; + } + + layout->setStretch(0, outerStretch); + layout->setStretch(1, widgetStretch); + layout->setStretch(2, outerStretch); +} + +void LcdDisplayDock::resizeEvent(QResizeEvent *event) { + // Keeping aspect ratio based on + // https://stackoverflow.com/questions/30005540/keeping-the-aspect-ratio-of-a-sub-classed-qwidget-during-resize + + update_layout(event->size().width(), event->size().height()); + + Super::resizeEvent(event); } diff --git a/qtmips_gui/lcddisplaydock.h b/qtmips_gui/lcddisplaydock.h index 9a4f866..4659fa5 100644 --- a/qtmips_gui/lcddisplaydock.h +++ b/qtmips_gui/lcddisplaydock.h @@ -37,20 +37,28 @@ #define LCDDISPLAYDOCK_H #include <QDockWidget> +#include <QBoxLayout> #include "lcddisplayview.h" #include "qtmipsmachine.h" class LcdDisplayDock : public QDockWidget { Q_OBJECT + + using Super = QDockWidget; + public: LcdDisplayDock(QWidget *parent, QSettings *settings); ~LcdDisplayDock(); + virtual void resizeEvent(QResizeEvent *event) override; void setup(machine::LcdDisplay *lcd_display); //public slots: private: + void update_layout(int w, int h); + + QBoxLayout *layout; LcdDisplayView *lcd_display_widget; }; diff --git a/qtmips_gui/lcddisplayview.cpp b/qtmips_gui/lcddisplayview.cpp index 450e7d4..b186610 100644 --- a/qtmips_gui/lcddisplayview.cpp +++ b/qtmips_gui/lcddisplayview.cpp @@ -1,4 +1,5 @@ #include <QPainter> +#include <QPaintEvent> #include <QStyle> #include "lcddisplay.h" #include "lcddisplayview.h" @@ -6,6 +7,8 @@ LcdDisplayView::LcdDisplayView(QWidget *parent) : Super(parent) { setMinimumSize(100, 100); fb_pixels = nullptr; + scale_x = 1.0; + scale_y = 1.0; } LcdDisplayView::~LcdDisplayView() { @@ -21,19 +24,45 @@ void LcdDisplayView::setup(machine::LcdDisplay *lcd_display) { if (fb_pixels != nullptr) delete fb_pixels; fb_pixels = nullptr; - fb_pixels = new QImage(lcd_display->height(), - lcd_display->width(), QImage::Format_RGB32); + fb_pixels = new QImage(lcd_display->width(), + lcd_display->height(), QImage::Format_RGB32); fb_pixels->fill(qRgb(0, 0, 0)); + update_scale(); update(); } void LcdDisplayView::pixel_update(uint x, uint y, uint r, uint g, uint b) { + int x1, y1, x2, y2; if (fb_pixels != nullptr) { fb_pixels->setPixel(x, y, qRgb(r, g, b)); - update(); + x1 = x * scale_x - 2; + if (x1 < 0) + x1 = 0; + x2 = x * scale_x + 2; + if (x2 > width()) + x2 = width(); + y1 = y * scale_y - 2; + if (y1 < 0) + y1 = 0; + y2 = y * scale_y + 2; + if (y2 > height()) + y2 = height(); + update(x1, y1, x2 - x1, y2 - y1); } } +void LcdDisplayView::update_scale() { + if (fb_pixels != nullptr) { + if ((fb_pixels->width() != 0) && (fb_pixels->height() != 0)) { + scale_x = (float)width() / fb_pixels->width(); + scale_y = (float)height() / fb_pixels->height(); + return; + } + } + scale_x = 1.0; + scale_y = 1.0; +} + void LcdDisplayView::paintEvent(QPaintEvent *event) { if (fb_pixels == nullptr) return Super::paintEvent(event); @@ -41,12 +70,28 @@ void LcdDisplayView::paintEvent(QPaintEvent *event) { return Super::paintEvent(event); QPainter painter(this); - QSize widgetSize = rect().size(); - const auto newHeight = widgetSize.width() * fb_pixels->height() / fb_pixels->width(); - if(newHeight <= widgetSize.height()) - widgetSize.setHeight(newHeight); - else - widgetSize.setWidth(widgetSize.height() * fb_pixels->width() / fb_pixels->height()); - painter.drawImage(rect(), fb_pixels->scaled(widgetSize)); + painter.drawImage(rect(), *fb_pixels); +#if 0 + painter.setPen(QPen(QColor(255, 255, 0))); + painter.drawLine(event->rect().topLeft(),event->rect().topRight()); + painter.drawLine(event->rect().topLeft(),event->rect().bottomLeft()); + painter.drawLine(event->rect().topLeft(),event->rect().bottomRight()); +#endif +} + +void LcdDisplayView::resizeEvent(QResizeEvent *event) { + Super::resizeEvent(event); + update_scale(); } +uint LcdDisplayView::fb_width() { + if (fb_pixels == nullptr) + return 0; + return fb_pixels->width(); +} + +uint LcdDisplayView::fb_height() { + if (fb_pixels == nullptr) + return 0; + return fb_pixels->height(); +} diff --git a/qtmips_gui/lcddisplayview.h b/qtmips_gui/lcddisplayview.h index 010a106..461bffc 100644 --- a/qtmips_gui/lcddisplayview.h +++ b/qtmips_gui/lcddisplayview.h @@ -17,15 +17,21 @@ public: ~LcdDisplayView(); void setup(machine::LcdDisplay *lcd_display); + uint fb_width(); + uint fb_height(); public slots: void pixel_update(uint x, uint y, uint r, uint g, uint b); protected: virtual void paintEvent(QPaintEvent *event) override; + virtual void resizeEvent(QResizeEvent *event) override; private: - QImage *fb_pixels; + void update_scale(); + float scale_x; + float scale_y; + QImage *fb_pixels; }; #endif // LCDDISPLAYVIEW_H |