From a3e3cf22d84be710b0d22d59427fd73a4f9dc165 Mon Sep 17 00:00:00 2001 From: Markus Gans Date: Thu, 7 Feb 2019 23:05:50 +0100 Subject: [PATCH] Add a "dynamic layout" Chapter into the first steps document --- ChangeLog | 5 +- doc/first-steps.md | 124 ++++++++++++++++++++++++++++++++++- examples/calculator.cpp | 4 +- examples/mandelbrot.cpp | 4 +- examples/menu.cpp | 4 +- examples/term-attributes.cpp | 4 +- examples/treeview.cpp | 4 +- examples/ui.cpp | 2 +- examples/windows.cpp | 4 +- src/fwindow.cpp | 5 +- 10 files changed, 141 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index d6061aef..f90263c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,9 @@ +2019-02-07 Markus Gans + * Add a "dynamic layout" Chapter into the first steps document + 2019-01-30 Markus Gans * Printing an FColorPair object can change the foreground and - background colors + background color 2019-01-27 Markus Gans * The print command can now have an FPoint object as a parameter diff --git a/doc/first-steps.md b/doc/first-steps.md index 5d5561b2..457d83a3 100644 --- a/doc/first-steps.md +++ b/doc/first-steps.md @@ -15,6 +15,7 @@ Table of Contents - [Callback function](#example-of-a-callback-function) - [Callback method](#example-of-a-callback-function) - [Custom signals](#send-custom-signals) +- [Dynamic layout](#dynamic-layout) @@ -287,7 +288,7 @@ class dialogWidget : public FDialog } private: - virtual void onTimer (FTimerEvent* ev) + virtual void onTimer (FTimerEvent* ev) override { if ( id == ev->getTimerId() && n < 9999999999 ) { @@ -666,4 +667,123 @@ the above program with gcc: ```cpp g++ -O2 -lfinal -std=c++11 emit-signal.cpp -o emit-signal ``` -The FINAL CUT widgets emit the following default signals: + + +Dynamic layout +-------------- + +A modern terminal emulation like xterm has no fixed resolution. +They offer the possibility to change the height and width of the +terminal at any time. That triggers a resize-event that calls +the `adjustSize()` method. This method allows adapting the widget +to a changed terminal size. You can override the `adjustSize()` +method to adjust the size and position of the widget. The method +`adjustSize()` will also be called indirectly via calling methods +`setGeometry()`, `setX()`, `setY()`, `setPos()`, `setWidth()`, +`setHeight()`, `setSize()`, `setTopPadding()`, `setLeftPadding()`, +`setBottomPadding()`, `setRightPadding()`, or `setDoubleFlatLine()`. + +Scalable dialogs derived from FDialog can change the dialog size by +clicking on the lower right corner of the window. You can intercept +a scaling action by overriding the `setSize()` method and adjusting +the client widgets. + +**File:** *size-adjustment.cpp* +```cpp +#include + +using namespace finalcut; + +class dialogWidget : public FDialog +{ + public: + explicit dialogWidget (FWidget* parent = nullptr) + : FDialog(parent) + { + setText ("Dialog"); + setResizeable(); + btn.setGeometry (FPoint(1, 1), FSize(12, 1), false); + line.setGeometry (FPoint(2, 3), FSize(12, 1), false); + // Set dialog geometry and calling adjustSize() + setGeometry (FPoint(25, 5), FSize(40, 12)); + setMinimumSize (FSize(25, 9)); + } + + private: + inline void checkMinValue (int& n) + { + if ( n < 1 ) // Checks and corrects the minimum value + n = 1; + } + + void centerDialog() + { + auto x = int((getDesktopWidth() - getWidth()) / 2); + auto y = int((getDesktopHeight() - getHeight()) / 2); + checkMinValue(x); + checkMinValue(y); + setPos (FPoint(x, y), false); + } + + void adjustWidgets() + { + auto bx = int(getWidth() - btn.getWidth() - 3); + auto by = int(getHeight() - 4); + btn.setPos (FPoint(bx, by), false); + line.setWidth (getWidth() - 4); + auto ly = int(getHeight() / 2) - 1; + line.setY (ly, false); + } + + virtual void adjustSize() override + { + // Calling super class method adjustSize() + FDialog::adjustSize(); + // Centers the dialog in the terminal + centerDialog(); + } + + virtual void setSize (const FSize& size, bool) override + { + // Calling super class methods setSize() + adjustSize() + FDialog::setSize (size, false); + FDialog::adjustSize(); + } + + virtual void draw() override + { + adjustWidgets(); // Adjust widgets before drawing + + // Calling super class method draw() + FDialog::draw(); + + print() << FPoint (3, 3) + << FColorPair (fc::Black, fc::White) + << "Text on " + << FColorPair (fc::Blue, fc::Yellow) + << "top"; + } + + FLineEdit line{"Middle", this}; + FButton btn{"&Bottom", this}; +}; + +int main (int argc, char* argv[]) +{ + FApplication app(argc, argv); + dialogWidget dialog(&app); + app.setMainWidget(&dialog); + dialog.show(); + return app.exec(); +} +``` +*(Note: You can close the window with the mouse, +Shift+F10 or Ctrl+^)* + + +After entering the source code in *size-adjustment.cpp* you can compile +the above program with gcc: +```cpp +g++ -O2 -lfinal -std=c++11 size-adjustment.cpp -o size-adjustment +``` + diff --git a/examples/calculator.cpp b/examples/calculator.cpp index 442b9d3b..ed5d7735 100644 --- a/examples/calculator.cpp +++ b/examples/calculator.cpp @@ -1081,8 +1081,8 @@ void Calc::cb_buttonClicked (finalcut::FWidget*, FDataPtr data) //---------------------------------------------------------------------- void Calc::adjustSize() { - std::size_t pw = getParentWidget()->getWidth(); - std::size_t ph = getParentWidget()->getHeight(); + std::size_t pw = getDesktopWidth(); + std::size_t ph = getDesktopHeight(); setX (1 + int(pw - getWidth()) / 2, false); setY (1 + int(ph - getHeight()) / 2, false); finalcut::FDialog::adjustSize(); diff --git a/examples/mandelbrot.cpp b/examples/mandelbrot.cpp index 40e6211b..fcec73af 100644 --- a/examples/mandelbrot.cpp +++ b/examples/mandelbrot.cpp @@ -142,8 +142,8 @@ void Mandelbrot::onClose (finalcut::FCloseEvent* ev) //---------------------------------------------------------------------- void Mandelbrot::adjustSize() { - std::size_t h = getParentWidget()->getHeight() - 1; - std::size_t w = getParentWidget()->getWidth() - 10; + std::size_t h = getDesktopHeight() - 1; + std::size_t w = getDesktopWidth() - 10; setGeometry(FPoint(6, 1), FSize(w, h), false); finalcut::FDialog::adjustSize(); } diff --git a/examples/menu.cpp b/examples/menu.cpp index bf19d379..6d2d682a 100644 --- a/examples/menu.cpp +++ b/examples/menu.cpp @@ -291,8 +291,8 @@ void Menu::defaultCallback (finalcut::FMenuList* mb) //---------------------------------------------------------------------- void Menu::adjustSize() { - int pw = int(getParentWidget()->getWidth()); - int ph = int(getParentWidget()->getHeight()); + int pw = int(getDesktopWidth()); + int ph = int(getDesktopHeight()); setX (1 + (pw - int(getWidth())) / 2, false); setY (1 + (ph - int(getHeight())) / 4, false); finalcut::FDialog::adjustSize(); diff --git a/examples/term-attributes.cpp b/examples/term-attributes.cpp index d134e96c..e0e9fce3 100644 --- a/examples/term-attributes.cpp +++ b/examples/term-attributes.cpp @@ -173,8 +173,8 @@ void AttribDlg::cb_back (finalcut::FWidget*, FDataPtr) //---------------------------------------------------------------------- void AttribDlg::adjustSize() { - int x = int((getParentWidget()->getWidth() - getWidth()) / 2); - int y = int((getParentWidget()->getHeight() - getHeight()) / 2) + 1; + int x = int((getDesktopWidth() - getWidth()) / 2); + int y = int((getDesktopHeight() - getHeight()) / 2) + 1; if ( x < 1 ) x = 1; diff --git a/examples/treeview.cpp b/examples/treeview.cpp index 0b622e6c..9de90baa 100644 --- a/examples/treeview.cpp +++ b/examples/treeview.cpp @@ -381,9 +381,9 @@ Treeview::~Treeview() // destructor //---------------------------------------------------------------------- void Treeview::adjustSize() { - std::size_t h = getParentWidget()->getHeight() - 4; + std::size_t h = getDesktopHeight() - 4; setHeight (h, false); - int X = int((getParentWidget()->getWidth() - getWidth()) / 2); + int X = int((getDesktopWidth() - getWidth()) / 2); if ( X < 1 ) X = 1; diff --git a/examples/ui.cpp b/examples/ui.cpp index 1351b8ed..d9751249 100644 --- a/examples/ui.cpp +++ b/examples/ui.cpp @@ -745,7 +745,7 @@ void MyDialog::adjustSize() { auto h = getParentWidget()->getHeight() - 4; setHeight (h, false); - auto X = int((getParentWidget()->getWidth() - getWidth()) / 2); + auto X = int((getDesktopWidth() - getWidth()) / 2); if ( X < 1 ) X = 1; diff --git a/examples/windows.cpp b/examples/windows.cpp index 2b316484..1cd2e8f6 100644 --- a/examples/windows.cpp +++ b/examples/windows.cpp @@ -346,8 +346,8 @@ void Window::activateWindow (finalcut::FDialog* win) //---------------------------------------------------------------------- void Window::adjustSize() { - std::size_t w = getRootWidget()->getWidth(); - std::size_t h = getRootWidget()->getHeight(); + std::size_t w = getDesktopWidth(); + std::size_t h = getDesktopHeight(); int X = int(1 + (w - 40) / 2) , Y = int(1 + (h - 22) / 2) , dx = ( w > 80 ) ? int(w - 80) / 2 : 0 diff --git a/src/fwindow.cpp b/src/fwindow.cpp index f8d7e790..95ce6b13 100644 --- a/src/fwindow.cpp +++ b/src/fwindow.cpp @@ -388,9 +388,8 @@ void FWindow::setGeometry ( const FPoint& p, const FSize& size, bool adjust) int old_x = getX(); int old_y = getY(); - std::size_t old_width = getWidth(); - std::size_t old_height = getHeight(); FPoint pos = p; + FSize old_size = getSize(); if ( pos.getY() < 1 ) pos.setY(1); @@ -400,7 +399,7 @@ void FWindow::setGeometry ( const FPoint& p, const FSize& size, bool adjust) if ( ! isVirtualWindow() ) return; - if ( getWidth() != old_width || getHeight() != old_height ) + if ( getSize() != old_size ) { FRect geometry = getTermGeometry(); geometry.move(-1, -1);