36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/UiUiUi.h:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2022 Dirk Hillbrecht
3 |
4 | #pragma once
5 |
6 | /** \mainpage UiUiUi - A User interface library for micro controllers.
7 | *
8 | * UiUiUi is a library for user interfaces.
9 | * It is aimed at micro controller platforms like Arduino, ESP32 or ESP8266.
10 | * It uses U8g2 as foundation for accessing the display hardware
11 | * so it runs on a vast number of displays.
12 | *
13 | * You incorporate UiUiUi into your project by one of two alternative ways:
14 | *
15 | * 1. Include `UiUiUi.h` to access the whole library and all widget types.
16 | * Use this if you design a complex interface and compile time does not matter.
17 | * 2. In smaller projects, you can simply include the header files of the classes
18 | * you need directly. It makes no difference and all subsequently needed files
19 | * will be loaded internally anyway.
20 | *
21 | * For more documentation, read through the widgets or visit the project page on Github.
22 | */
23 |
24 | // Basic helper classes and definitions
25 | #include "UIEnums.h"
26 | #include "UIPoint.h"
27 | #include "UISize.h"
28 | #include "UIArea.h"
29 |
30 | // Simple widgets
31 | #include "UIWidget.h"
32 | #include "UITextLine.h"
33 | #include "UITextIcon.h"
34 | #include "UIHorizontalLine.h"
35 | #include "UIVerticalLine.h"
36 | #include "UICheckerboard.h"
37 | #include "UIEnvelope.h"
38 | #include "UIBitmap.h"
39 |
40 | // Widget groups
41 | #include "UIWidgetGroup.h"
42 | #include "UIRows.h"
43 | #include "UIColumns.h"
44 | #include "UICards.h"
45 |
46 | // Topmost class
47 | #include "UIDisplay.h"
48 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This library is licensed under the terms of
2 | the new-bsd license (two-clause bsd license).
3 | See also: http://www.opensource.org/licenses/bsd-license.php
4 |
5 | ============ BSD License for UiUiUi Code ============
6 |
7 | The UiUiUi user interface library
8 |
9 | Copyright (c) 2022, Dirk Hillbrecht, Germany, dirk@hillbrecht.de
10 | All rights reserved.
11 |
12 | Redistribution and use in source and binary forms, with or without modification,
13 | are permitted provided that the following conditions are met:
14 |
15 | * Redistributions of source code must retain the above copyright notice, this list
16 | of conditions and the following disclaimer.
17 |
18 | * Redistributions in binary form must reproduce the above copyright notice, this
19 | list of conditions and the following disclaimer in the documentation and/or other
20 | materials provided with the distribution.
21 |
22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23 | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
27 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
34 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 |
36 |
--------------------------------------------------------------------------------
/docs/api/search/all_e.js:
--------------------------------------------------------------------------------
1 | var searchData=
2 | [
3 | ['set_0',['set',['../classUIArea.html#a1617bf5c5d663431f544ad05d19fd0fb',1,'UIArea::set(uint16_t left, uint16_t top, uint16_t right, uint16_t bottom)'],['../classUIArea.html#a2df3798555f84f9bf93cdb95e06ef9fc',1,'UIArea::set(const UIArea *source)'],['../classUIArea.html#ade8b3e83421758986203819b7761de46',1,'UIArea::set(UIPoint *topLeft, UISize *size)'],['../classUIArea.html#ae088e1e24afe82c89acb73d442edfae1',1,'UIArea::set(UIPoint *topLeft, uint16_t width, uint16_t height)'],['../classUISize.html#ac031e8aa126d50c1e156d9643cc111f4',1,'UISize::set(uint16_t width, uint16_t height)'],['../classUISize.html#a3f013656fe8f1a6cd5c73bb86410f16b',1,'UISize::set(UISize *other)']]],
4 | ['setfrom_1',['setFrom',['../classUIPoint.html#a39126e3bb65f5543fd501ffd91d23737',1,'UIPoint']]],
5 | ['setparent_2',['setParent',['../classUIWidget.html#acc38f64ab731edb952ff28862bc3c739',1,'UIWidget']]],
6 | ['settext_3',['setText',['../classUITextLine.html#a8d9753b7e803a05036e1c2b58513acb7',1,'UITextLine']]],
7 | ['setupdatetiles_4',['setUpdateTiles',['../classUIDisplay.html#a010833082aba3c241378cf00221ccb68',1,'UIDisplay']]],
8 | ['setvisiblewidget_5',['setVisibleWidget',['../classUICards.html#a78edc57ecec545eed27976c0d02445f4',1,'UICards']]],
9 | ['showfirstwidget_6',['showFirstWidget',['../classUICards.html#a78938eb265311d20ddd448dafa8b4784',1,'UICards']]],
10 | ['shrink_7',['shrink',['../classUIArea.html#a59bde38e1f6a1539ec2012e2b5012756',1,'UIArea']]],
11 | ['shrinkto_8',['shrinkTo',['../classUISize.html#a8b8723a86118f59b1e01324ef43f2122',1,'UISize']]],
12 | ['signalneedsrendering_9',['signalNeedsRendering',['../classUIWidget.html#a4b5254b86930c189bf82e511fb8b5e12',1,'UIWidget']]]
13 | ];
14 |
--------------------------------------------------------------------------------
/docs/api/search/functions_b.js:
--------------------------------------------------------------------------------
1 | var searchData=
2 | [
3 | ['set_0',['set',['../classUIArea.html#a1617bf5c5d663431f544ad05d19fd0fb',1,'UIArea::set(uint16_t left, uint16_t top, uint16_t right, uint16_t bottom)'],['../classUIArea.html#a2df3798555f84f9bf93cdb95e06ef9fc',1,'UIArea::set(const UIArea *source)'],['../classUIArea.html#ade8b3e83421758986203819b7761de46',1,'UIArea::set(UIPoint *topLeft, UISize *size)'],['../classUIArea.html#ae088e1e24afe82c89acb73d442edfae1',1,'UIArea::set(UIPoint *topLeft, uint16_t width, uint16_t height)'],['../classUISize.html#ac031e8aa126d50c1e156d9643cc111f4',1,'UISize::set(uint16_t width, uint16_t height)'],['../classUISize.html#a3f013656fe8f1a6cd5c73bb86410f16b',1,'UISize::set(UISize *other)']]],
4 | ['setfrom_1',['setFrom',['../classUIPoint.html#a39126e3bb65f5543fd501ffd91d23737',1,'UIPoint']]],
5 | ['setparent_2',['setParent',['../classUIWidget.html#acc38f64ab731edb952ff28862bc3c739',1,'UIWidget']]],
6 | ['settext_3',['setText',['../classUITextLine.html#a8d9753b7e803a05036e1c2b58513acb7',1,'UITextLine']]],
7 | ['setupdatetiles_4',['setUpdateTiles',['../classUIDisplay.html#a010833082aba3c241378cf00221ccb68',1,'UIDisplay']]],
8 | ['setvisiblewidget_5',['setVisibleWidget',['../classUICards.html#a78edc57ecec545eed27976c0d02445f4',1,'UICards']]],
9 | ['showfirstwidget_6',['showFirstWidget',['../classUICards.html#a78938eb265311d20ddd448dafa8b4784',1,'UICards']]],
10 | ['shrink_7',['shrink',['../classUIArea.html#a59bde38e1f6a1539ec2012e2b5012756',1,'UIArea']]],
11 | ['shrinkto_8',['shrinkTo',['../classUISize.html#a8b8723a86118f59b1e01324ef43f2122',1,'UISize']]],
12 | ['signalneedsrendering_9',['signalNeedsRendering',['../classUIWidget.html#a4b5254b86930c189bf82e511fb8b5e12',1,'UIWidget']]]
13 | ];
14 |
--------------------------------------------------------------------------------
/src/UIColumns.cpp:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2022 Dirk Hillbrecht
3 |
4 | #pragma once
5 |
6 | #include "Arduino.h"
7 | #include
8 |
9 | #include "UIArea.h"
10 | #include "UIWidget.h"
11 | #include "UIWidgetGroup.h"
12 | #include "UIColumns.h"
13 |
14 |
15 | /* Create a group of column-wise arranged sub-widgets */
16 | UIColumns::UIColumns(UIWidget* firstChild,UIWidget* next):
17 | UIWidgetGroup(firstChild,next) {}
18 |
19 | /* Layout all the sub-widgets one next to the other. */
20 | void UIColumns::layout(U8G2* display,UIArea* dim) {
21 | UIWidgetGroup::layout(display,dim);
22 | UIArea stamp=UIArea(dim);
23 | stamp.right=stamp.left;
24 | int extendingWidth=(extendingChildrenCount==0 || fixedWidth>=(dim->right-dim->left)?0:((dim->right-dim->left)-fixedWidth)/extendingChildrenCount);
25 | UIWidget* widget=firstChild;
26 | while (widget && stamp.rightright) {
27 | int requestedWidth=widget->preferredSize(display).width;
28 | stamp.right=min(dim->right,(uint16_t)(stamp.right+(requestedWidth==UISize::MAX_LEN?extendingWidth:requestedWidth)));
29 | widget->layout(display,&stamp);
30 | widget=widget->next;
31 | stamp.left=stamp.right;
32 | }
33 | }
34 |
35 | /* Preferred size of a columns group is computed by attaching the sub-widgets appropriately. */
36 | void UIColumns::computePreferredSize(U8G2 *display,UISize *preferredSize) {
37 | UIWidget* elem=firstChild;
38 | while (elem) {
39 | UISize otherDim=elem->preferredSize(display);
40 | if (otherDim.width==UISize::MAX_LEN)
41 | extendingChildrenCount+=1;
42 | else
43 | fixedWidth+=otherDim.width;
44 | preferredSize->cumulateWidthMaxHeight(&otherDim);
45 | elem=elem->next;
46 | }
47 | }
48 |
49 | // end of file
50 |
--------------------------------------------------------------------------------
/src/UIRows.h:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2022 Dirk Hillbrecht
3 |
4 | #pragma once
5 |
6 | #include "Arduino.h"
7 | #include
8 |
9 | #include "UIArea.h"
10 | #include "UIWidget.h"
11 | #include "UIWidgetGroup.h"
12 |
13 |
14 | /** Widget group for widgets organized in rows one below the other.
15 | *
16 | * The sub-widgets are layouted one below the other from top to bottom
17 | * in the area the UIRows widgets group gets from the higher layout level.
18 | *
19 | * The preferred size is the sum of the preferred heights of all sub-widgets
20 | * and the maximum of the widths of the sub-widgets.
21 | *
22 | * Sub-widgets can request either a fixed height or "as high as possible"
23 | * by returning UISize::MAX_LEN as preferred height.
24 | * In this case in the layout step the remainder of the assigned widget height
25 | * and all fixed heights of subwidgets
26 | * is split evenly between all "as large as possible" heights.
27 | */
28 | class UIRows: public UIWidgetGroup {
29 |
30 | public:
31 |
32 | /** Create a group of row-wise arranged sub-widgets */
33 | UIRows(UIWidget* firstChild,UIWidget* next=nullptr);
34 |
35 | /** Layout all the sub-widgets one below the other. */
36 | void layout(U8G2* display,UIArea* dim);
37 |
38 | protected:
39 |
40 | /** Preferred size of a rows group is computed by stacking the sub-widgets appropriately. */
41 | void computePreferredSize(U8G2 *display,UISize *preferredSize);
42 |
43 | private:
44 |
45 | /** Number of sub-widgets which want to be "as high as possible" */
46 | uint8_t extendingChildrenCount;
47 |
48 | /** Sum of all fixed height preferences (not "as high as possible") of the sub-widgets. */
49 | uint16_t fixedHeight;
50 |
51 | };
52 |
53 | // end of file
54 |
--------------------------------------------------------------------------------
/src/UIColumns.h:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2022 Dirk Hillbrecht
3 |
4 | #pragma once
5 |
6 | #include "Arduino.h"
7 | #include
8 |
9 | #include "UIArea.h"
10 | #include "UIWidget.h"
11 | #include "UIWidgetGroup.h"
12 |
13 |
14 | /** Widget group for widgets organized in columns one next to the other.
15 | *
16 | * The sub-widgets are layouted one next to the other from left to right
17 | * in the area the UIColumns widgets group gets from the higher layout level.
18 | *
19 | * The preferred size is the sum of the preferred widths of all sub-widgets
20 | * and the maximum of the heights of the sub-widgets.
21 | *
22 | * Sub-widgets can request either a fixed width or "as wide as possible" by
23 | * returning UISize::MAX_LEN as preferred width.
24 | * In this case in the layout step the remainder of the assigned widget widths
25 | * and all fixed widths of subwidgets
26 | * is split evenly between all "as large as possible" widths.
27 | */
28 | class UIColumns: public UIWidgetGroup {
29 |
30 | public:
31 |
32 | /** Create a group of column-wise arranged sub-widgets */
33 | UIColumns(UIWidget* firstChild,UIWidget* next=nullptr);
34 |
35 | /** Layout all the sub-widgets one next to the other. */
36 | void layout(U8G2* display,UIArea* dim);
37 |
38 | protected:
39 |
40 | /** Preferred size of a columns group is computed by attaching the sub-widgets appropriately. */
41 | void computePreferredSize(U8G2 *display,UISize *preferredSize);
42 |
43 | private:
44 |
45 | /** Number of sub-widgets which want to be "as high as possible" */
46 | uint8_t extendingChildrenCount;
47 |
48 | /** Sum of all fixed height preferences (not "as high as possible") of the sub-widgets. */
49 | uint16_t fixedWidth;
50 |
51 | };
52 |
53 | // end of file
54 |
--------------------------------------------------------------------------------
/src/UIRows.cpp:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2022 Dirk Hillbrecht
3 |
4 | #include "Arduino.h"
5 | #include
6 |
7 | #include "UIArea.h"
8 | #include "UIWidget.h"
9 | #include "UIWidgetGroup.h"
10 | #include "UIRows.h"
11 |
12 |
13 | /* Create a group of row-wise arranged sub-widgets */
14 | UIRows::UIRows(UIWidget* firstChild,UIWidget* next):
15 | UIWidgetGroup(firstChild,next) {}
16 |
17 | /* Layout all the sub-widgets one below the other. */
18 | void UIRows::layout(U8G2* display,UIArea* dim) {
19 | UIWidgetGroup::layout(display,dim); // Call inherited method.
20 | UIArea stamp=UIArea(dim); // Use this stamp for the areas of the sub-widgets
21 | stamp.bottom=stamp.top;
22 | // extendingHeight is the height which the widgets get who want to be "as high as possible"
23 | int extendingHeight=(extendingChildrenCount==0 || fixedHeight>=(dim->bottom-dim->top)?0:((dim->bottom-dim->top)-fixedHeight)/extendingChildrenCount);
24 | UIWidget* widget=firstChild;
25 | while (widget && stamp.bottombottom) { // Walk through the widgets
26 | int requestedHeight=widget->preferredSize(display).height;
27 | // Bottom is top plus height of the current widget
28 | stamp.bottom=min(dim->bottom,(uint16_t)(stamp.bottom+(requestedHeight==UISize::MAX_LEN?extendingHeight:requestedHeight)));
29 | widget->layout(display,&stamp);
30 | widget=widget->next;
31 | // For next widget, top will be current bottom
32 | stamp.top=stamp.bottom;
33 | }
34 | }
35 |
36 | /* Preferred size of a rows group is computed by stacking the sub-widgets appripriately. */
37 | void UIRows::computePreferredSize(U8G2 *display,UISize *preferredSize) {
38 | UIWidget* elem=firstChild;
39 | while (elem) {
40 | UISize otherDim=elem->preferredSize(display);
41 | if (otherDim.height==UISize::MAX_LEN)
42 | extendingChildrenCount+=1;
43 | else
44 | fixedHeight+=otherDim.height;
45 | preferredSize->maxWidthCumulateHeight(&otherDim);
46 | elem=elem->next;
47 | }
48 | }
49 |
50 | // end of file
51 |
--------------------------------------------------------------------------------
/src/UIBitmap.h:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2023 Andrew Burks
3 |
4 | #pragma once
5 |
6 | #include "Arduino.h"
7 | #include
8 |
9 | #include "UIEnums.h"
10 | #include "UIPoint.h"
11 | #include "UISize.h"
12 | #include "UIArea.h"
13 | #include "UIWidget.h"
14 |
15 |
16 | /** A widget containing a bitmap (XBMP) which is set statically during compile time.
17 | *
18 | * Height and width must be supplied to match the XBMP data.
19 | * Alignment can be specified for cases where the bitmap is rendered in a larger area.
20 | */
21 | class UIBitmap : public UIWidget {
22 |
23 | public:
24 |
25 | /** Create a bitmap with supplied alignment and potential successor.
26 | *
27 | * The supplied width and height must match the bitmap data.
28 | * The bitmap data must be XBMP formated, and compiled into PROGMEM. */
29 | UIBitmap(uint16_t width, uint16_t height, const uint8_t *bitmap, UIAlignment alignment, UIWidget* next = nullptr);
30 |
31 | /** Create a bitmap with default centered alignment and potential successor.
32 | *
33 | * The supplied width and height must match the bitmap data.
34 | * The bitmap data must be XBMP formated, and compiled into PROGMEM. */
35 | UIBitmap(uint16_t width, uint16_t height, const uint8_t *bitmap, UIWidget* next = nullptr);
36 |
37 | /** A bitmap is only rendered if the rendering is forced, otherwise it never changes. */
38 | UIArea* render(U8G2* display,bool force);
39 |
40 | protected:
41 |
42 | /** Generate the preferred size from the bitmap size. */
43 | void computePreferredSize(U8G2 *display,UISize *preferredSize);
44 |
45 | private:
46 |
47 | /** The image to render, as a pointer to XBMP data in PROGMEM. */
48 | const uint8_t* bitmap;
49 |
50 | /** Size of the currently rendered text. */
51 | UISize imageSize;
52 |
53 | /** Alignment of the image in the widget's area */
54 | UIAlignment alignment;
55 |
56 | /** Top left point of where the text to render. */
57 | UIPoint topLeft;
58 |
59 |
60 | };
61 |
62 | // end of file
63 |
--------------------------------------------------------------------------------
/src/UICards.cpp:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2022 Dirk Hillbrecht
3 |
4 | #pragma once
5 |
6 | #include "Arduino.h"
7 | #include
8 |
9 | // Basic helper classes and definitions
10 | #include "UIEnums.h"
11 | #include "UIPoint.h"
12 | #include "UISize.h"
13 | #include "UIArea.h"
14 |
15 | // Simple widgets
16 | #include "UIWidget.h"
17 | #include "UIWidgetGroup.h"
18 | #include "UICards.h"
19 |
20 |
21 | UICards::UICards(UIWidget* firstChild,UIWidget* next):
22 | UIWidgetGroup(firstChild,next),visible(nullptr) {}
23 |
24 | void UICards::layout(U8G2* display,UIArea* dim) {
25 | UIWidgetGroup::layout(display,dim);
26 | UIWidget* widget=firstChild;
27 | while (widget) {
28 | widget->layout(display,dim);
29 | widget=widget->next;
30 | }
31 | }
32 |
33 | void UICards::setVisibleWidget(UIWidget *visible) {
34 | if (this->visible!=visible) {
35 | this->visible=visible;
36 | this->forceInternally=true;
37 | signalNeedsRendering();
38 | }
39 | }
40 |
41 | void UICards::hide() {
42 | setVisibleWidget(nullptr);
43 | }
44 |
45 | void UICards::showFirstWidget() {
46 | setVisibleWidget(firstChild);
47 | }
48 |
49 | UIArea* UICards::render(U8G2 *display,bool force) {
50 | if (this->forceInternally) {
51 | clip(display);
52 | clearFull(display);
53 | if (visible)
54 | visible->render(display,true);
55 | this->forceInternally=false;
56 | this->renderChildren=false;
57 | return &dim;
58 | }
59 | else if (force || this->renderChildren) {
60 | UIArea *retval=(visible?visible->render(display,force):&UIArea::EMPTY);
61 | this->renderChildren=false;
62 | return retval;
63 | }
64 | else
65 | return &UIArea::EMPTY;
66 | }
67 |
68 | void UICards::computePreferredSize(U8G2 *display,UISize *preferredSize) {
69 | UIWidget* elem=firstChild;
70 | while (elem) {
71 | UISize otherSize=elem->preferredSize(display);
72 | preferredSize->maxBoth(&otherSize);
73 | elem=elem->next;
74 | }
75 | }
76 |
77 | void UICards::childNeedsRendering(UIWidget *child) {
78 | if (child==visible)
79 | UIWidgetGroup::childNeedsRendering(child);
80 | }
81 |
82 | // end of file
83 |
--------------------------------------------------------------------------------
/docs/api/classUIWidget__inherit__graph.map:
--------------------------------------------------------------------------------
1 |
15 |
--------------------------------------------------------------------------------
/src/UIWidgetGroup.h:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2022 Dirk Hillbrecht
3 |
4 | #pragma once
5 |
6 | #include "Arduino.h"
7 | #include
8 |
9 | #include "UIArea.h"
10 | #include "UIWidget.h"
11 | #include "UIParent.h"
12 |
13 | /** Main abstraction of a group of interface widgets.
14 | *
15 | * A widget group organizes a number of widgets in a certain way.
16 | * These organized widgets form a linked list via their "next" pointers.
17 | * The widget group gets the first of these widgets as their "first widget".
18 | *
19 | * As a widget group itself is also a widget, it has itself potentially a successor
20 | * which allows forming another widget group on a "higher level".
21 | *
22 | * Widget groups are the key to create complex interfaces with UiUiUi.
23 | * Be sure to understand the concept behind them.
24 | *
25 | * As with the UIWidget class, UIWidgetGroup itself only implements a tiny portion
26 | * of the business logic. The derived classes actually create a semantic onto the
27 | * grouped widgets, e.g. aligning them horizontally or vertically.
28 | */
29 | class UIWidgetGroup: public UIWidget, public UIParent {
30 |
31 | public:
32 |
33 | /** Create a widget group with a linked list of sub-widgets and a potential successor. */
34 | UIWidgetGroup(UIWidget* firstChild,UIWidget* next=nullptr);
35 |
36 | /** Default implementation of rendering a widget group is to render all of its sub-widgets. */
37 | UIArea* render(U8G2* display,bool force);
38 |
39 | /** Called by any child of this group to indicate that it wants to be rendered. */
40 | virtual void childNeedsRendering(UIWidget *child);
41 |
42 | protected:
43 |
44 | /** The first of the widgets grouped by this widget group. */
45 | UIWidget* firstChild;
46 |
47 | /** Flag whether any child of this group needs to be rendered. */
48 | bool renderChildren;
49 | // Note: This is protected as UICards handles this on its own.
50 | // With a better abstraction, this could be made private.
51 |
52 | private:
53 |
54 | /** Space where the rendering information of all sub-widgets is collected. */
55 | UIArea rendered;
56 |
57 | };
58 |
59 | // end of file
60 |
--------------------------------------------------------------------------------
/src/UIBitmap.cpp:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2023 Andrew Burks
3 |
4 | #include "Arduino.h"
5 | #include
6 |
7 | #include "UIEnums.h"
8 | #include "UIPoint.h"
9 | #include "UISize.h"
10 | #include "UIArea.h"
11 | #include "UIWidget.h"
12 | #include "UIBitmap.h"
13 |
14 | /* Create a bitmap with the given width, height, XBMP, alignment, and potential successor*/
15 | UIBitmap::UIBitmap(uint16_t width, uint16_t height, const uint8_t *bitmap, UIAlignment alignment, UIWidget* next):
16 | UIWidget(next),imageSize(width,height),bitmap(bitmap),alignment(alignment) {}
17 |
18 | /* Create a bitmap with the given width, height, XBMP, and potential successor*/
19 | UIBitmap::UIBitmap(uint16_t width, uint16_t height, const uint8_t *bitmap, UIWidget* next):
20 | UIBitmap(width,height,bitmap,UIAlignment::Center,next) {}
21 |
22 | UIArea* UIBitmap::render(U8G2* display,bool force) {
23 | // Only render image if forced
24 | if (force && dim.hasArea()) {
25 | clip(display); // Clip every drawing to the frame buffer to this component's area.
26 | clearBox(display,&dim); // Clear the entire widget area, even unused buffer/border
27 | display->setDrawColor(1); // Setup painting
28 | display->setBitmapMode(1);
29 | UISize actualSize = dim.getSize();//get the available screen size and check if it is big enough for the bitmap
30 | if(actualSize.width >= imageSize.width && actualSize.height >= imageSize.height){
31 | topLeft.setFrom(dim.alignedTopLeft(alignment,&imageSize));
32 | display->drawXBMP(topLeft.x, topLeft.y, imageSize.width, imageSize.height, bitmap);//draw the bitmap
33 | } else { //just draw a box with an X through it if the supplied area is not big enough
34 | display->drawFrame(dim.left, dim.top, actualSize.width, actualSize.height);
35 | display->drawLine(dim.left, dim.top, dim.right-1, dim.bottom-1);
36 | display->drawLine(dim.left, dim.bottom-1, dim.right-1, dim.top);
37 | }
38 | return &dim;//return the entire widget area because the background was cleared
39 | }
40 | else // No need to render: Return empty area
41 | return &UIArea::EMPTY;
42 | } // render()
43 |
44 | void UIBitmap::computePreferredSize(U8G2 *display,UISize *preferredSize) {
45 | preferredSize->set(&imageSize);
46 | }
47 |
48 | // end of file
49 |
--------------------------------------------------------------------------------
/src/UISize.cpp:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2022 Dirk Hillbrecht
3 |
4 | #include "Arduino.h"
5 | #include "UISize.h"
6 |
7 | /** Representation of a size, i.e. a width and a height. */
8 |
9 | const uint16_t UISize::MAX_LEN=32767; // Half of max value so that addition of two does not overflow
10 |
11 | const UISize MAX_SIZE=UISize(UISize::MAX_LEN,UISize::MAX_LEN);
12 |
13 | const UISize EMPTY=UISize();
14 |
15 | UISize::UISize(uint16_t width,uint16_t height): width(width), height(height) {}
16 |
17 | UISize::UISize(UISize *other): UISize(other->width,other->height) {}
18 |
19 | UISize::UISize(): UISize(0,0) {}
20 |
21 | void UISize::set(uint16_t width,uint16_t height) { this->width=width; this->height=height; }
22 |
23 | void UISize::set(UISize *other) { set(other->width,other->height); }
24 |
25 | void UISize::cumulateBoth(UISize *other) {
26 | width=max_len_or(width+other->width);
27 | height=max_len_or(height+other->height);
28 | }
29 |
30 | void UISize::maxWidthCumulateHeight(UISize *other) {
31 | width=my_max(width,other->width);
32 | height=max_len_or(height+other->height);
33 | }
34 |
35 | void UISize::cumulateWidthMaxHeight(UISize *other) {
36 | width=max_len_or(width+other->width);
37 | height=my_max(height,other->height);
38 | }
39 |
40 | void UISize::maxBoth(UISize *other) {
41 | width=my_max(width,other->width);
42 | height=my_max(height,other->height);
43 | }
44 |
45 | void UISize::shrinkTo(UISize *other) {
46 | if (other->widthwidth;
48 | if (other->heightheight;
50 | }
51 |
52 | bool UISize::isEmpty() {
53 | return width==0 && height==0;
54 | }
55 |
56 | /* Static helper method: maximum of two given uint16_t fields */
57 | uint16_t UISize::my_max(uint16_t a,uint16_t b) {
58 | return (a>b?a:b);
59 | }
60 |
61 | /* Static helper method: maximum of two given uint16_t fields */
62 | uint16_t UISize::my_min(uint16_t a,uint16_t b) {
63 | return (a
21 |
22 | // And we load the complete UiUiUi library with the combining header file
23 | #include
24 |
25 |
26 | // **************************
27 | // *** Global definitions ***
28 | // **************************
29 |
30 | // As usual, the representation of the display hardware is defined globally and statically at the begin
31 |
32 | // Define your display here, this is for a Heltec WiFi LoRa 32
33 | U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 15, /* data=*/ 4, /* reset=*/ 16);
34 |
35 | // *** UI definition ***
36 |
37 | // Now, the UI is defined. This also happens statically and globally.
38 | // We have a very simple UI here: Apart from the display manager, it consists of only one element
39 |
40 | // Line which shows the time, will render itself centered on its space
41 | UITextLine textLine=UITextLine(u8g2_font_6x10_tf);
42 |
43 | // As the time line is the only UI element, just put it into the display representation.
44 | // It will get the complete space and render itself centered in both directions.
45 | UIDisplay displayManager=UIDisplay(&textLine);
46 |
47 |
48 | // ********************
49 | // *** Main control ***
50 | // ********************
51 |
52 | /* Setup function: Called once after boot */
53 | void setup() {
54 |
55 | // Init U8g2, this is done outside of UiUiUi
56 | u8g2.begin();
57 |
58 | // Set an initial text on the text line.
59 | // As everything in the interface is static, this can even be done
60 | // before the interface itself is initialized.
61 | textLine.setText("Hello World");
62 |
63 | // Now init the interface including layouting and initial rendering
64 | displayManager.init(&u8g2);
65 |
66 | }
67 |
68 | /* Loop function: Nothing to be done here. */
69 | void loop() {
70 | delay(1000);
71 | }
72 |
73 | // end of file
74 |
--------------------------------------------------------------------------------
/docs/api/search/all_2.js:
--------------------------------------------------------------------------------
1 | var searchData=
2 | [
3 | ['childneedsrendering_0',['childNeedsRendering',['../classUIDisplay.html#a50eb83c52dacff5d19dcbade92a9b03e',1,'UIDisplay::childNeedsRendering()'],['../classUIEnvelope.html#a8a704af40e1ae1879eac155b59b243b7',1,'UIEnvelope::childNeedsRendering()'],['../classUIParent.html#afb810c16a19d101603cb7b8f80925552',1,'UIParent::childNeedsRendering()'],['../classUIWidgetGroup.html#afe578f6322c50fc3eb898a917fd663ae',1,'UIWidgetGroup::childNeedsRendering()'],['../classUICards.html#a99300a0b4840d4128a3dcc97d7dca858',1,'UICards::childNeedsRendering()']]],
4 | ['clear_1',['clear',['../classUIArea.html#a83f22286aabb4441dc6a580d472c9ce7',1,'UIArea']]],
5 | ['clearbox_2',['clearBox',['../classUIWidget.html#a29e8a19a079bac9039d5d9db26746152',1,'UIWidget']]],
6 | ['clearfull_3',['clearFull',['../classUIWidget.html#ae2e24ff3027c86094ece175376a06b85',1,'UIWidget']]],
7 | ['cleartext_4',['clearText',['../classUITextLine.html#a78916cdade7701203801d395c09e1a44',1,'UITextLine']]],
8 | ['clip_5',['clip',['../classUIWidget.html#a227359ef6c879bbd5fdfee8c2e991a35',1,'UIWidget']]],
9 | ['computepreferredsize_6',['computePreferredSize',['../classUICards.html#a7e233813c55e0fa0a96ee7b397d49dab',1,'UICards::computePreferredSize()'],['../classUIWidget.html#ab3afd35739547f9b32a5da5d7d373383',1,'UIWidget::computePreferredSize()'],['../classUIVerticalLine.html#a289366a90394587d5d07476e08778063',1,'UIVerticalLine::computePreferredSize()'],['../classUITextLine.html#a2c8f5be4b16474bd48bfa7f66a2904d5',1,'UITextLine::computePreferredSize()'],['../classUITextIcon.html#af6608f9a0a55dc1845a3e0a5581d1ec4',1,'UITextIcon::computePreferredSize()'],['../classUIRows.html#a78c8a29833def59f2af3169be1a4b5e3',1,'UIRows::computePreferredSize()'],['../classUIHorizontalLine.html#ad5bd610276a1cf50eaa9a7aeb1b0b4e9',1,'UIHorizontalLine::computePreferredSize()'],['../classUIEnvelope.html#a875c4011fa68895593601a3245fd6c14',1,'UIEnvelope::computePreferredSize()'],['../classUIColumns.html#a8e65d7120199131da3e587257e6b6314',1,'UIColumns::computePreferredSize()'],['../classUICheckerboard.html#a39a7ea37666c2a84b50a2527df70cbb6',1,'UICheckerboard::computePreferredSize()'],['../classUIBitmap.html#a2f4543cb76ca96f6aa290624e7f2f8d6',1,'UIBitmap::computePreferredSize()']]],
10 | ['cumulateboth_7',['cumulateBoth',['../classUISize.html#a3088b8aa55e0dcb530ebfbbbbe48aae5',1,'UISize']]],
11 | ['cumulatewidthmaxheight_8',['cumulateWidthMaxHeight',['../classUISize.html#ae7aa9a6de97badde7a5e671c50ca15b9',1,'UISize']]]
12 | ];
13 |
--------------------------------------------------------------------------------
/docs/api/search/functions_1.js:
--------------------------------------------------------------------------------
1 | var searchData=
2 | [
3 | ['childneedsrendering_0',['childNeedsRendering',['../classUIDisplay.html#a50eb83c52dacff5d19dcbade92a9b03e',1,'UIDisplay::childNeedsRendering()'],['../classUIEnvelope.html#a8a704af40e1ae1879eac155b59b243b7',1,'UIEnvelope::childNeedsRendering()'],['../classUIParent.html#afb810c16a19d101603cb7b8f80925552',1,'UIParent::childNeedsRendering()'],['../classUIWidgetGroup.html#afe578f6322c50fc3eb898a917fd663ae',1,'UIWidgetGroup::childNeedsRendering()'],['../classUICards.html#a99300a0b4840d4128a3dcc97d7dca858',1,'UICards::childNeedsRendering()']]],
4 | ['clear_1',['clear',['../classUIArea.html#a83f22286aabb4441dc6a580d472c9ce7',1,'UIArea']]],
5 | ['clearbox_2',['clearBox',['../classUIWidget.html#a29e8a19a079bac9039d5d9db26746152',1,'UIWidget']]],
6 | ['clearfull_3',['clearFull',['../classUIWidget.html#ae2e24ff3027c86094ece175376a06b85',1,'UIWidget']]],
7 | ['cleartext_4',['clearText',['../classUITextLine.html#a78916cdade7701203801d395c09e1a44',1,'UITextLine']]],
8 | ['clip_5',['clip',['../classUIWidget.html#a227359ef6c879bbd5fdfee8c2e991a35',1,'UIWidget']]],
9 | ['computepreferredsize_6',['computePreferredSize',['../classUICards.html#a7e233813c55e0fa0a96ee7b397d49dab',1,'UICards::computePreferredSize()'],['../classUIWidget.html#ab3afd35739547f9b32a5da5d7d373383',1,'UIWidget::computePreferredSize()'],['../classUIVerticalLine.html#a289366a90394587d5d07476e08778063',1,'UIVerticalLine::computePreferredSize()'],['../classUITextLine.html#a2c8f5be4b16474bd48bfa7f66a2904d5',1,'UITextLine::computePreferredSize()'],['../classUITextIcon.html#af6608f9a0a55dc1845a3e0a5581d1ec4',1,'UITextIcon::computePreferredSize()'],['../classUIRows.html#a78c8a29833def59f2af3169be1a4b5e3',1,'UIRows::computePreferredSize()'],['../classUIHorizontalLine.html#ad5bd610276a1cf50eaa9a7aeb1b0b4e9',1,'UIHorizontalLine::computePreferredSize()'],['../classUIEnvelope.html#a875c4011fa68895593601a3245fd6c14',1,'UIEnvelope::computePreferredSize()'],['../classUIColumns.html#a8e65d7120199131da3e587257e6b6314',1,'UIColumns::computePreferredSize()'],['../classUICheckerboard.html#a39a7ea37666c2a84b50a2527df70cbb6',1,'UICheckerboard::computePreferredSize()'],['../classUIBitmap.html#a2f4543cb76ca96f6aa290624e7f2f8d6',1,'UIBitmap::computePreferredSize()']]],
10 | ['cumulateboth_7',['cumulateBoth',['../classUISize.html#a3088b8aa55e0dcb530ebfbbbbe48aae5',1,'UISize']]],
11 | ['cumulatewidthmaxheight_8',['cumulateWidthMaxHeight',['../classUISize.html#ae7aa9a6de97badde7a5e671c50ca15b9',1,'UISize']]]
12 | ];
13 |
--------------------------------------------------------------------------------
/docs/api/inherit_graph_1.map:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/src/UIEnvelope.cpp:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2022 Dirk Hillbrecht
3 |
4 | #pragma once
5 |
6 | #include "Arduino.h"
7 | #include
8 |
9 | #include "UIEnums.h"
10 | #include "UIPoint.h"
11 | #include "UISize.h"
12 | #include "UIArea.h"
13 | #include "UIWidget.h"
14 | #include "UIEnvelope.h"
15 |
16 |
17 | UIEnvelope::UIEnvelope(UIExpansion expansion,UIAlignment alignment,UISize borderSize,UIWidget* content,UIWidget* next):
18 | UIWidget(next), expansion(expansion), alignment(alignment), borderSize(borderSize), content(content) {
19 | if (content)
20 | content->setParent(this);
21 | }
22 |
23 | UIEnvelope::UIEnvelope(UIExpansion expansion,UIAlignment alignment,UIWidget* content,UIWidget* next):
24 | UIEnvelope(expansion,alignment,UISize(),content,next) {}
25 |
26 | void UIEnvelope::layout(U8G2 *display,UIArea *dim) {
27 | UIWidget::layout(display,dim);
28 | if (content) {
29 | UIArea contentDim=UIArea(dim);
30 | contentDim.shrink(&borderSize);
31 | UISize contentSize=contentDim.getSize();
32 | UISize preferredContentSize=content->preferredSize(display);
33 | if (preferredContentSize.widthlayout(display,&contentDim);
39 | }
40 | }
41 |
42 | void UIEnvelope::childNeedsRendering(UIWidget *child) {
43 | signalNeedsRendering(); // just pass signal to parent
44 | }
45 |
46 | UIArea* UIEnvelope::render(U8G2 *display,bool force) {
47 | if (force) {
48 | clearFull(display);
49 | if (content)
50 | content->render(display,true);
51 | return &dim;
52 | }
53 | else
54 | return (content?content->render(display,false):&UIArea::EMPTY);
55 | }
56 |
57 | void UIEnvelope::computePreferredSize(U8G2 *display,UISize *preferredSize) {
58 | if (content) {
59 | UISize contentSize=content->preferredSize(display);
60 | preferredSize->set(&contentSize);
61 | }
62 | if (expansion==UIExpansion::Horizontal || expansion==UIExpansion::Both)
63 | preferredSize->width=UISize::MAX_LEN;
64 | if (expansion==UIExpansion::Vertical || expansion==UIExpansion::Both)
65 | preferredSize->height=UISize::MAX_LEN;
66 | preferredSize->cumulateBoth(&borderSize);
67 | preferredSize->cumulateBoth(&borderSize);//double because borderSize dimensions only represent half of the contrinuted thickness
68 | }
69 |
70 | // end of file
71 |
--------------------------------------------------------------------------------
/src/UISize.h:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2022 Dirk Hillbrecht
3 |
4 | #pragma once
5 |
6 | #include "Arduino.h"
7 |
8 | /** Representation of a size, i.e. a width and a height. */
9 | class UISize final {
10 | public:
11 | /** Less than half of max value so that addition of two does not overflow */
12 | static const uint16_t MAX_LEN;
13 |
14 | /** UISize representing maximal size in all directions */
15 | static const UISize MAX_SIZE;
16 |
17 | /** UISize representing an empty size (both directions 0) */
18 | static const UISize EMPTY;
19 |
20 | /** Initialize a size from a width and a height. */
21 | UISize(uint16_t width,uint16_t height);
22 |
23 | /** Initialize a size from another size */
24 | UISize(UISize *other);
25 |
26 | /** Initialize a size without width or height (both 0). */
27 | UISize();
28 |
29 | /** Width */
30 | uint16_t width;
31 |
32 | /** Height */
33 | uint16_t height;
34 |
35 | /** Set height from a numeric width and height. */
36 | void set(uint16_t width,uint16_t height);
37 |
38 | /** Set size from another referenced height */
39 | void set(UISize *other);
40 |
41 | /** Cumulate width and height of this and the referenced size into this size. */
42 | void cumulateBoth(UISize *other);
43 |
44 | /** Cumulate the heights of this and the other size and take the maximum of both widths,
45 | * write everything into this. */
46 | void maxWidthCumulateHeight(UISize *other);
47 |
48 | /** Cumulate the widths of this and the other size and take the maximum of both heights,
49 | * write everything into this. */
50 | void cumulateWidthMaxHeight(UISize *other);
51 |
52 | /** Take the maximum of widths and height of this and the other size and write it into this. */
53 | void maxBoth(UISize *other);
54 |
55 | /** Shrink this so that neither width nor height is larger than the one of other. */
56 | void shrinkTo(UISize *other);
57 |
58 | /** Return true if this size is empty, i.e. it has neither width nor height, i.e. both are 0. */
59 | bool isEmpty();
60 |
61 | /** Static helper method: maximum of two given uint16_t fields */
62 | static uint16_t my_max(uint16_t a,uint16_t b);
63 |
64 | /** Static helper method: maximum of two given uint16_t fields */
65 | static uint16_t my_min(uint16_t a,uint16_t b);
66 |
67 | /** Static helper method: restrict given value to MAX_LEN at most. */
68 | static uint16_t max_len_or(uint16_t a);
69 |
70 | /** Debug output of this size with some prepended label. */
71 | void debugPrint(const char* label);
72 |
73 | };
74 |
75 | // end of file
76 |
--------------------------------------------------------------------------------
/docs/api/search/mag_sel.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
75 |
--------------------------------------------------------------------------------
/src/UICards.h:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2022 Dirk Hillbrecht
3 |
4 | #pragma once
5 |
6 | #include "Arduino.h"
7 | #include
8 |
9 | // Basic helper classes and definitions
10 | #include "UIEnums.h"
11 | #include "UIPoint.h"
12 | #include "UISize.h"
13 | #include "UIArea.h"
14 |
15 | // Simple widgets
16 | #include "UIWidget.h"
17 | #include "UIWidgetGroup.h"
18 |
19 |
20 | /** Widget group which shows nothing or exactly one of its sub-widgets
21 | *
22 | * UICards takes its widgets and shows exactly one of them covering the whole area.
23 | * This is like a card stack (therefore the name).
24 | * The widget to show is selected by setVisibleWidget().
25 | *
26 | * If the visible widget is not set or set to null, nothing is shown.
27 | *
28 | * Note that you can use UICards easily to make another widget visible or invisible:
29 | * Just add the widget in question as first (and only) sub-widget to UICards.
30 | * Then, if you make it the visible widget, it is shown, and if you set the visible widget
31 | * to null, it is hidden.
32 | *
33 | * The two methods `hide()` and `showFirstWidget()` act as syntactic sugar for this operation mode.
34 | */
35 | class UICards: public UIWidgetGroup {
36 |
37 | public:
38 |
39 | /** Initialize the cards widget with the first widget and a potential successor on the same level. */
40 | UICards(UIWidget* firstChild,UIWidget* next=nullptr);
41 |
42 | /** Layout the cards widget. */
43 | void layout(U8G2* display,UIArea* dim);
44 |
45 | /** Set the widget to show on the area of the cards widget group.
46 | *
47 | * If nullptr is given, nothing is shown.
48 | * The parameter *must* be one of the sub-widgets of the group.
49 | * If another widget is passed, the results are undefined.
50 | *
51 | * Changing the visible widget leads to the cards widget group being completely re-rendered.
52 | */
53 | void setVisibleWidget(UIWidget *visible);
54 |
55 | /** Shortcut: Hide all widgets, clear the UICards area on the display. */
56 | void hide();
57 |
58 | /** Shortcut: Show first widget. */
59 | void showFirstWidget();
60 |
61 | /** Render the cards widget group onto the display. */
62 | UIArea* render(U8G2 *display,bool force);
63 |
64 | /** UICards will consider the render request from the child only if it is the currently visible child. */
65 | void childNeedsRendering(UIWidget *child);
66 |
67 | protected:
68 |
69 | /** Compute the preferred size as the maximum envelope of the preferred sizes of all subwidgets. */
70 | void computePreferredSize(U8G2 *display,UISize *preferredSize);
71 |
72 | private:
73 |
74 | /** Pointer to the visible widget. */
75 | UIWidget *visible;
76 |
77 | /** Flag whether redraw has to take place. */
78 | bool forceInternally;
79 |
80 | };
81 |
82 | // end of file
83 |
--------------------------------------------------------------------------------
/src/UIEnvelope.h:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2022 Dirk Hillbrecht
3 |
4 | #pragma once
5 |
6 | #include "Arduino.h"
7 | #include
8 |
9 | #include "UIEnums.h"
10 | #include "UIPoint.h"
11 | #include "UISize.h"
12 | #include "UIArea.h"
13 | #include "UIWidget.h"
14 | #include "UIParent.h"
15 |
16 |
17 | /** Envelope widget which contains exactly one other widget and changes its representation.
18 | *
19 | * The envelope can do the following things:
20 | *
21 | * * If the enclosed widget does not spawn the whole display area it is assigned,
22 | * the envelope can place it with a certain alignment.
23 | * * The envelope can add a border to the inner widget. This border will be empty.
24 | * * If the inner widget prefers to be smaller than it could be, the envelope can report
25 | * a larger area to the caller.
26 | */
27 | class UIEnvelope : public UIWidget, public UIParent {
28 | public:
29 |
30 | /** Create an envelope widget.
31 | *
32 | * @param expansion Report an enlarged preferred size to the caller for the axes given by this parameter.
33 | * @param alignment Align the content widget this way if it is smaller than the area of the envelope.
34 | * @param borderSize Generate an empty border of this size around the content widget
35 | * @param content The content of the envelope. If empty, the envelope renders an empty area.
36 | * @param next Next widget on the same level as the envelope.
37 | */
38 | UIEnvelope(UIExpansion expansion,UIAlignment alignment,UISize borderSize=UISize(),UIWidget* content=nullptr,UIWidget* next=nullptr);
39 |
40 | /** Create an envelope widget without border.
41 | *
42 | * @param expansion Report an enlarged preferred size to the caller for the axes given by this parameter.
43 | * @param alignment Align the content widget this way if it is smaller than the area of the envelope.
44 | * @param content The content of the envelope. If empty, the envelope renders an empty area.
45 | * @param next Next widget on the same level as the envelope.
46 | */
47 | UIEnvelope(UIExpansion expansion,UIAlignment alignment,UIWidget* content,UIWidget* next=nullptr);
48 |
49 | /** Layout the envelope.
50 | *
51 | * This includes shaping the content according to all the constraints.
52 | */
53 | void layout(U8G2 *display,UIArea *dim);
54 |
55 | /** Render the envelope - which also renders the content if it exists. */
56 | UIArea* render(U8G2 *display,bool force);
57 |
58 | /** Called by the child of this envelope to indicate that it wants to be rendered. */
59 | void childNeedsRendering(UIWidget *child);
60 |
61 | protected:
62 |
63 | /** Compute the preferred size which is determined by the content by may be changed by the envelope. */
64 | void computePreferredSize(U8G2 *display,UISize *preferredSize);
65 |
66 | private:
67 |
68 | /** Expansion strategy during computation of preferred size. */
69 | UIExpansion expansion;
70 |
71 | /** Alignment of inner content widget. */
72 | UIAlignment alignment;
73 |
74 | /** Border size of the envelope. */
75 | UISize borderSize;
76 |
77 | /** Reference to the content widget of the envelope. */
78 | UIWidget* content;
79 |
80 | };
81 |
82 | // end of file
83 |
--------------------------------------------------------------------------------
/examples/EnvelopeAroundChecker/EnvelopeAroundChecker.ino:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: BSD-2-Clause
2 | // (C) 2022 Dirk Hillbrecht
3 |
4 | // Show how an envelope can be placed around a widget
5 |
6 | // **************************
7 | // *** Include statements ***
8 | // **************************
9 |
10 | // You need the U8g2 library
11 | #include
12 |
13 | // And we load the complete UiUiUi library with the combining header file
14 | #include
15 |
16 |
17 | // **************************
18 | // *** Global definitions ***
19 | // **************************
20 |
21 | // As usual, the representation of the display hardware is defined globally and statically at the begin
22 |
23 | // Define your display here, this is for a Heltec WiFi LoRa 32
24 | U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 15, /* data=*/ 4, /* reset=*/ 16);
25 |
26 | // *** UI definition ***
27 |
28 | // The UI is a frame around the whole display, then a border of 10 pixels
29 | // on the left and right and 5 pixels on top and bottom and then a
30 | // checkerboard.
31 |
32 | // This is a static example. It just defines this interface and draws it.
33 | // After that, nothing more happens. If you want to have an example
34 | // with some interaction, use EnvelopedCheckerboardAndButtons
35 | // where you can enable or disable the presentation of the checkerboard.
36 |
37 | // *** Define the UI ***
38 |
39 | // As usual, we define the UI widget from bottom to top.
40 |
41 | // We draw the outer frame out of four lines. This is the bottom one.
42 | UIHorizontalLine bottomLine=UIHorizontalLine();
43 |
44 | // ...and here is the right one. Note that these lines are
45 | // totally unrelated, they will be connected via the groups later on.
46 | UIVerticalLine rightLine=UIVerticalLine();
47 |
48 | // Now comes the checkerboard which likes to get as large as possible.
49 | UICheckerboard checkerboard=UICheckerboard(UISize(UISize::MAX_LEN,UISize::MAX_LEN));
50 | // Note: This should work, too. But for me in my ESP32 development environment,
51 | // this line triggers a linker error.
52 | //UICheckerboard checkerboard=UICheckerboard(UISize::MAX_SIZE);
53 |
54 | // It gets an envelope around it where it is placed in the center
55 | UIEnvelope checkerEnv=UIEnvelope(UIExpansion::Both,UIAlignment::Center,UISize(10,5),&checkerboard,&rightLine);
56 |
57 | // The lieft line of the outer border
58 | UIVerticalLine leftLine=UIVerticalLine(&checkerEnv);
59 |
60 | // The inner group: Connecting left line, enveloped checkerboard and right line
61 | UIColumns centerWidgets=UIColumns(&leftLine,&bottomLine);
62 |
63 | // The top line, the last line still missing
64 | UIHorizontalLine topLine=UIHorizontalLine(¢erWidgets);
65 |
66 | // The outer group: Connecting top line, inner group and bottom line
67 | UIRows fullScreen=UIRows(&topLine);
68 |
69 | // Display representation taking the row group as display-filling child.
70 | UIDisplay displayManager=UIDisplay(&fullScreen);
71 |
72 |
73 | // Now set it up.
74 | void setup() {
75 | Serial.begin(115200); // For debugging purposes only, not used by sketch otherwise
76 |
77 | // Initialize the display
78 | u8g2.begin(); // Init U8g2, this is done outside of UiUiUi
79 | displayManager.init(&u8g2); // Initialize the display manager
80 |
81 | }
82 |
83 | // Each run of loop() draws the checkerboard with a different setting of first and follow update tiles.
84 | void loop() {
85 | delay(1000);
86 | }
87 |
88 | // end of file
89 |
--------------------------------------------------------------------------------