5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
23 uint8_t THEME_ICONS
[] = {
34 Layout
* currentScreen
;
35 WidgetsContainerInterface
* currentContainer
;
36 Widget
* currentWidget
;
38 bool widgetNeedsSettings
;
40 #define SCREENS_SETUP_2ND_COLUMN 200
42 char fileSelection
[LEN_ZONE_OPTION_STRING
];
43 uint8_t fileSelectionDone
;
45 int updateMainviewsMenu();
46 bool menuScreenAdd(event_t event
);
47 void onScreenSetupMenu(const char * result
);
49 void onZoneOptionFileSelectionMenu(const char * result
)
51 if (result
== STR_UPDATE_LIST
) {
52 if (!sdListFiles(BITMAPS_PATH
, BITMAPS_EXT
, LEN_ZONE_OPTION_STRING
, NULL
)) {
53 POPUP_WARNING(STR_NO_BITMAPS_ON_SD
);
57 fileSelectionDone
= true;
58 memcpy(fileSelection
, result
, sizeof(fileSelection
));
62 uint8_t getZoneOptionColumns(const ZoneOption
* option
)
64 if (option
->type
== ZoneOption::Color
) {
65 return uint8_t(2 | NAVIGATION_LINE_BY_LINE
);
72 uint8_t editColorPart(coord_t x
, coord_t y
, event_t event
, uint8_t part
, uint8_t value
, LcdFlags attr
, uint32_t i_flags
)
74 const char * STR_COLOR_PARTS
= "\002" "R:" "G:" "B:";
75 uint8_t PART_BITS
[] = { 5, 6, 5 };
76 lcdDrawTextAtIndex(x
, y
, STR_COLOR_PARTS
, part
, (attr
&& menuHorizontalPosition
< 0) ? TEXT_INVERTED_COLOR
: TEXT_COLOR
);
77 lcdDrawNumber(x
+ 20, y
, value
<< (8-PART_BITS
[part
]), LEFT
|TEXT_COLOR
|((attr
&& (menuHorizontalPosition
< 0 || menuHorizontalPosition
== part
)) ? attr
: TEXT_COLOR
));
78 if (attr
&& menuHorizontalPosition
== part
) {
79 value
= checkIncDec(event
, value
, 0, (1 << PART_BITS
[part
])-1, i_flags
);
84 bool editZoneOption(coord_t y
, const ZoneOption
* option
, ZoneOptionValue
* value
, LcdFlags attr
, uint32_t i_flags
, event_t event
)
86 lcdDrawText(MENUS_MARGIN_LEFT
, y
, option
->name
);
88 if (option
->type
== ZoneOption::Bool
) {
89 value
->boolValue
= editCheckBox(value
->boolValue
, SCREENS_SETUP_2ND_COLUMN
, y
, attr
, event
); // TODO always does storageDirty(EE_MODEL)
91 else if (option
->type
== ZoneOption::Integer
) {
92 lcdDrawNumber(SCREENS_SETUP_2ND_COLUMN
, y
, value
->signedValue
, attr
| LEFT
);
94 CHECK_INCDEC_MODELVAR(event
, value
->signedValue
, option
->min
.signedValue
, option
->max
.signedValue
); // TODO i_flags
97 else if (option
->type
== ZoneOption::String
) {
98 editName(SCREENS_SETUP_2ND_COLUMN
, y
, value
->stringValue
, sizeof(value
->stringValue
), event
, attr
); // TODO i_flags?
100 else if (option
->type
== ZoneOption::File
) {
101 if (ZEXIST(value
->stringValue
))
102 lcdDrawSizedText(SCREENS_SETUP_2ND_COLUMN
, y
, value
->stringValue
, sizeof(value
->stringValue
), attr
);
104 lcdDrawTextAtIndex(SCREENS_SETUP_2ND_COLUMN
, y
, STR_VCSWFUNC
, 0, attr
); // TODO define
106 if (event
==EVT_KEY_FIRST(KEY_ENTER
)) {
108 if (sdListFiles(BITMAPS_PATH
, BITMAPS_EXT
, sizeof(value
->stringValue
), value
->stringValue
, LIST_NONE_SD_FILE
)) {
109 fileSelectionDone
= false;
110 POPUP_MENU_START(onZoneOptionFileSelectionMenu
);
113 POPUP_WARNING(STR_NO_BITMAPS_ON_SD
);
116 else if (fileSelectionDone
) {
117 memcpy(value
->stringValue
, fileSelection
, sizeof(fileSelection
));
118 fileSelectionDone
= false;
119 storageDirty(i_flags
);
123 else if (option
->type
== ZoneOption::TextSize
) {
124 lcdDrawTextAtIndex(SCREENS_SETUP_2ND_COLUMN
, y
, "\010StandardTiny\0 Small\0 Mid\0 Double", value
->unsignedValue
, attr
);
126 value
->unsignedValue
= checkIncDec(event
, value
->unsignedValue
, 0, 4, i_flags
);
129 else if (option
->type
== ZoneOption::Timer
) {
130 drawStringWithIndex(SCREENS_SETUP_2ND_COLUMN
, y
, STR_TIMER
, value
->unsignedValue
+ 1, attr
);
132 value
->unsignedValue
= checkIncDec(event
, value
->unsignedValue
, 0, MAX_TIMERS
- 1, i_flags
);
135 else if (option
->type
== ZoneOption::Source
) {
136 drawSource(SCREENS_SETUP_2ND_COLUMN
, y
, value
->unsignedValue
, attr
);
138 CHECK_INCDEC_MODELSOURCE(event
, value
->unsignedValue
, 1, MIXSRC_LAST_TELEM
);
141 else if (option
->type
== ZoneOption::Color
) {
142 RGB_SPLIT(value
->unsignedValue
, r
, g
, b
);
144 if (attr
&& menuHorizontalPosition
< 0) {
145 lcdDrawSolidFilledRect(SCREENS_SETUP_2ND_COLUMN
-3, y
-1, 230, FH
+1, TEXT_INVERTED_BGCOLOR
);
148 lcdSetColor(value
->unsignedValue
);
149 lcdDrawSolidFilledRect(SCREENS_SETUP_2ND_COLUMN
-1, y
+1, 42, 17, TEXT_COLOR
);
150 lcdDrawSolidFilledRect(SCREENS_SETUP_2ND_COLUMN
, y
+2, 40, 15, CUSTOM_COLOR
);
152 r
= editColorPart(SCREENS_SETUP_2ND_COLUMN
+ 50, y
, event
, 0, r
, attr
, i_flags
);
153 g
= editColorPart(SCREENS_SETUP_2ND_COLUMN
+ 110, y
, event
, 1, g
, attr
, i_flags
);
154 b
= editColorPart(SCREENS_SETUP_2ND_COLUMN
+ 170, y
, event
, 2, b
, attr
, i_flags
);
156 if (attr
&& checkIncDec_Ret
) {
157 value
->unsignedValue
= RGB_JOIN(r
, g
, b
);
161 return (attr
&& checkIncDec_Ret
);
164 int getOptionsCount(const ZoneOption
* options
)
166 if (options
== NULL
) {
171 for (const ZoneOption
* option
= options
; option
->name
; option
++) {
179 bool menuSettings(const char * title
, T
* object
, uint32_t i_flags
, event_t event
)
182 if (object
->getErrorMessage()) {
183 // display error instead of widget settings
184 // TODO nicer display (proper word-wrap)
185 SIMPLE_SUBMENU("Widget Error", ICON_MODEL_LUA_SCRIPTS
, 1);
186 int len
= strlen(object
->getErrorMessage());
188 const char * p
= object
->getErrorMessage();
190 lcdDrawSizedText(MENUS_MARGIN_LEFT
, y
, p
, 30);
198 const ZoneOption
* options
= object
->getOptions();
199 linesCount
= getOptionsCount(options
);
200 uint8_t mstate_tab
[MAX_WIDGET_OPTIONS
];
201 for (int i
=0; i
<linesCount
; i
++) {
202 mstate_tab
[i
] = getZoneOptionColumns(&options
[i
]);
205 CUSTOM_SUBMENU_WITH_OPTIONS(title
, ICON_THEME
, linesCount
, OPTION_MENU_TITLE_BAR
);
207 for (int i
=0; i
<NUM_BODY_LINES
+1; i
++) {
208 coord_t y
= MENU_CONTENT_TOP
+ i
* FH
;
209 int k
= i
+ menuVerticalOffset
;
210 LcdFlags blink
= ((s_editMode
>0) ? BLINK
|INVERS
: INVERS
);
211 LcdFlags attr
= (menuVerticalPosition
== k
? blink
: 0);
212 if (k
< linesCount
) {
213 const ZoneOption
* option
= &options
[k
];
214 ZoneOptionValue
* value
= object
->getOptionValue(k
);
215 if (editZoneOption(y
, option
, value
, attr
, i_flags
, event
)) {
224 bool menuWidgetSettings(event_t event
)
226 return menuSettings
<Widget
>(STR_WIDGET_SETTINGS
, currentWidget
, EE_MODEL
, event
);
229 bool menuWidgetChoice(event_t event
)
231 static Widget
* previousWidget
= NULL
;
232 static Widget
* currentWidget
= NULL
;
233 static std::list
<const WidgetFactory
*>::const_iterator iterator
;
234 static Widget::PersistentData tempData
;
239 previousWidget
= currentContainer
->getWidget(currentZone
);
240 currentContainer
->setWidget(currentZone
, NULL
);
241 iterator
= getRegisteredWidgets().cbegin();
242 if (previousWidget
) {
243 const WidgetFactory
* factory
= previousWidget
->getFactory();
244 std::list
<const WidgetFactory
*>::const_iterator it
= getRegisteredWidgets().cbegin();
245 for (; it
!= getRegisteredWidgets().cend(); ++it
) {
246 if (factory
->getName() == (*it
)->getName()) {
252 if (iterator
!= getRegisteredWidgets().cend())
253 currentWidget
= (*iterator
)->create(currentContainer
->getZone(currentZone
), &tempData
);
257 case EVT_KEY_FIRST(KEY_EXIT
):
258 if (previousWidget
) {
260 delete currentWidget
;
261 currentContainer
->setWidget(currentZone
, previousWidget
);
266 case EVT_KEY_FIRST(KEY_ENTER
):
267 if (iterator
!= getRegisteredWidgets().cend()) {
269 delete previousWidget
;
270 currentContainer
->createWidget(currentZone
, *iterator
);
271 widgetNeedsSettings
= currentContainer
->getWidget(currentZone
)->getFactory()->getOptions();
272 storageDirty(EE_MODEL
);
277 case EVT_ROTARY_RIGHT
:
278 if (iterator
!= getRegisteredWidgets().cend() && iterator
!= --getRegisteredWidgets().cend()) {
281 delete currentWidget
;
282 currentWidget
= (*iterator
)->create(currentContainer
->getZone(currentZone
), &tempData
);
286 case EVT_ROTARY_LEFT
:
287 if (iterator
!= getRegisteredWidgets().cbegin()) {
290 delete currentWidget
;
291 currentWidget
= (*iterator
)->create(currentContainer
->getZone(currentZone
), &tempData
);
296 currentScreen
->refresh();
298 Zone zone
= currentContainer
->getZone(currentZone
);
299 lcdDrawFilledRect(0, 0, zone
.x
-2, LCD_H
, SOLID
, OVERLAY_COLOR
| (8<<24));
300 lcdDrawFilledRect(zone
.x
+zone
.w
+2, 0, LCD_W
-zone
.x
-zone
.w
-2, LCD_H
, SOLID
, OVERLAY_COLOR
| (8<<24));
301 lcdDrawFilledRect(zone
.x
-2, 0, zone
.w
+4, zone
.y
-2, SOLID
, OVERLAY_COLOR
| (8<<24));
302 lcdDrawFilledRect(zone
.x
-2, zone
.y
+zone
.h
+2, zone
.w
+4, LCD_H
-zone
.y
-zone
.h
-2, SOLID
, OVERLAY_COLOR
| (8<<24));
305 currentWidget
->refresh();
307 if (iterator
!= getRegisteredWidgets().cbegin()) {
308 lcdDrawBitmapPattern(zone
.x
-10, zone
.y
+zone
.h
/2-10, LBM_SWIPE_CIRCLE
, TEXT_INVERTED_BGCOLOR
);
309 lcdDrawBitmapPattern(zone
.x
-10, zone
.y
+zone
.h
/2-10, LBM_SWIPE_LEFT
, TEXT_INVERTED_COLOR
);
311 if (iterator
!= --getRegisteredWidgets().cend()) {
312 lcdDrawBitmapPattern(zone
.x
+zone
.w
-9, zone
.y
+zone
.h
/2-10, LBM_SWIPE_CIRCLE
, TEXT_INVERTED_BGCOLOR
);
313 lcdDrawBitmapPattern(zone
.x
+zone
.w
-9, zone
.y
+zone
.h
/2-10, LBM_SWIPE_RIGHT
, TEXT_INVERTED_COLOR
);
316 lcdDrawText(zone
.x
+ zone
.w
, zone
.y
-1, currentWidget
->getFactory()->getName(), RIGHT
| TEXT_COLOR
| SMLSIZE
| INVERS
);
321 void onZoneMenu(const char * result
)
323 if (result
== STR_SELECT_WIDGET
) {
324 pushMenu(menuWidgetChoice
);
326 else if (result
== STR_WIDGET_SETTINGS
) {
327 pushMenu(menuWidgetSettings
);
329 else if (result
== STR_REMOVE_WIDGET
) {
330 currentContainer
->createWidget(currentZone
, NULL
);
331 storageDirty(EE_MODEL
);
335 bool menuWidgetsSetup(event_t event
)
339 menuVerticalPosition
= 0;
341 case EVT_KEY_FIRST(KEY_EXIT
):
342 killEvents(KEY_EXIT
);
347 currentScreen
->refresh();
349 for (int i
=currentContainer
->getZonesCount()-1; i
>=0; i
--) {
350 Zone zone
= currentContainer
->getZone(i
);
352 int padding
, thickness
;
353 if (currentContainer
== topbar
) {
354 color
= MENU_TITLE_COLOR
;
359 color
= TEXT_INVERTED_BGCOLOR
;
363 if (menuVerticalPosition
== i
) {
364 lcdDrawSolidRect(zone
.x
-padding
, zone
.y
-padding
, zone
.w
+2*padding
, zone
.h
+2*padding
, thickness
, color
);
365 if (event
== EVT_KEY_FIRST(KEY_ENTER
)) {
366 killEvents(KEY_ENTER
);
367 currentZone
= menuVerticalPosition
;
368 currentWidget
= currentContainer
->getWidget(menuVerticalPosition
);
370 POPUP_MENU_ADD_ITEM(STR_SELECT_WIDGET
);
371 if (currentWidget
->getFactory()->getOptions())
372 POPUP_MENU_ADD_ITEM(STR_WIDGET_SETTINGS
);
373 POPUP_MENU_ADD_ITEM(STR_REMOVE_WIDGET
);
374 POPUP_MENU_START(onZoneMenu
);
377 onZoneMenu(STR_SELECT_WIDGET
);
382 if (widgetNeedsSettings
) {
383 currentWidget
= currentContainer
->getWidget(menuVerticalPosition
);
385 widgetNeedsSettings
= false;
386 onZoneMenu(STR_WIDGET_SETTINGS
);
389 lcdDrawRect(zone
.x
-padding
, zone
.y
-padding
, zone
.w
+2*padding
, zone
.h
+2*padding
, thickness
, 0x3F, color
);
392 navigate(event
, currentContainer
->getZonesCount(), currentContainer
->getZonesCount(), 1);
397 T
* editThemeChoice(coord_t x
, coord_t y
, std::list
<T
*> & elList
, T
* current
, bool needsOffsetCheck
, LcdFlags attr
, event_t event
)
399 static uint8_t menuHorizontalOffset
= 0;
400 uint8_t elCount
= elList
.size(), last
, idx
;
402 int currentIndex
= 0;
403 typename
std::list
<T
*>::const_iterator elItr
= elList
.cbegin();
408 for (; elItr
!= elList
.cend(); ++elItr
, ++currentIndex
) {
409 if ((*elItr
) == current
)
413 if (event
== EVT_ENTRY
) {
414 menuHorizontalOffset
= 0;
415 needsOffsetCheck
= true;
418 if (needsOffsetCheck
) {
419 if (currentIndex
< menuHorizontalOffset
) {
420 menuHorizontalOffset
= currentIndex
;
422 else if (currentIndex
> menuHorizontalOffset
+ 3) {
423 menuHorizontalOffset
= currentIndex
- 3;
427 if (menuHorizontalPosition
< 0) {
428 lcdDrawSolidFilledRect(x
-3, y
-1, min
<uint8_t>(4, elCount
)*56+1, 2*FH
-5, TEXT_INVERTED_BGCOLOR
);
431 if (needsOffsetCheck
) {
432 menuHorizontalPosition
= currentIndex
;
434 else if (menuHorizontalPosition
< menuHorizontalOffset
) {
435 menuHorizontalOffset
= menuHorizontalPosition
;
437 else if (menuHorizontalPosition
> menuHorizontalOffset
+ 3) {
438 menuHorizontalOffset
= menuHorizontalPosition
- 3;
442 last
= min
<uint8_t>(menuHorizontalOffset
+ 4, elCount
);
443 idx
= menuHorizontalOffset
;
445 elItr
= elList
.cbegin();
446 std::advance(elItr
, min
<uint8_t>(menuHorizontalOffset
, elCount
- 1));
447 for (; idx
< last
&& elItr
!= elList
.cend(); ++idx
, ++elItr
, pos
+= 56) {
448 (*elItr
)->drawThumb(pos
, y
+1, current
== (*elItr
) ? ((attr
&& menuHorizontalPosition
< 0) ? TEXT_INVERTED_COLOR
: TEXT_INVERTED_BGCOLOR
) : LINE_COLOR
);
451 lcdDrawBitmapPattern(x
- 12, y
+1, LBM_CARROUSSEL_LEFT
, menuHorizontalOffset
> 0 ? LINE_COLOR
: CURVE_AXIS_COLOR
);
452 lcdDrawBitmapPattern(x
+ 4 * 56, y
+1, LBM_CARROUSSEL_RIGHT
, last
< getRegisteredLayouts().size() ? LINE_COLOR
: CURVE_AXIS_COLOR
);
454 if (attr
&& menuHorizontalPosition
>= 0) {
455 lcdDrawSolidRect(x
+ (menuHorizontalPosition
- menuHorizontalOffset
) * 56 - 3, y
- 1, 57, 35, 1, TEXT_INVERTED_BGCOLOR
);
456 if (event
== EVT_KEY_FIRST(KEY_ENTER
)) {
458 elItr
= elList
.cbegin();
459 if (menuHorizontalPosition
< (int)elList
.size())
460 std::advance(elItr
, menuHorizontalPosition
);
461 if (elItr
!= elList
.cend())
470 enum menuScreensThemeItems
{
471 ITEM_SCREEN_SETUP_THEME
,
472 ITEM_SCREEN_SETUP_THEME_OPTION1
= ITEM_SCREEN_SETUP_THEME
+2
475 bool menuScreensTheme(event_t event
)
477 bool needsOffsetCheck
= (menuVerticalPosition
!= 0 || menuHorizontalPosition
< 0);
478 const ZoneOption
* options
= theme
->getOptions();
479 int optionsCount
= getOptionsCount(options
);
480 linesCount
= ITEM_SCREEN_SETUP_THEME_OPTION1
+ optionsCount
+ 1;
482 menuPageCount
= updateMainviewsMenu();
483 uint8_t mstate_tab
[2 + MAX_THEME_OPTIONS
+ 1] = { uint8_t(NAVIGATION_LINE_BY_LINE
| uint8_t(getRegisteredThemes().size()-1)), ORPHAN_ROW
};
484 for (int i
=0; i
<optionsCount
; i
++) {
485 mstate_tab
[2+i
] = getZoneOptionColumns(&options
[i
]);
487 mstate_tab
[2+optionsCount
] = 0; // The button for the Topbar setup
488 CUSTOM_MENU_WITH_OPTIONS(STR_USER_INTERFACE
, THEME_ICONS
, menuTabScreensSetup
, menuPageCount
, 0, linesCount
);
490 for (int i
=0; i
<NUM_BODY_LINES
; i
++) {
491 coord_t y
= MENU_CONTENT_TOP
+ i
* FH
;
492 int k
= i
+ menuVerticalOffset
;
493 LcdFlags blink
= ((s_editMode
> 0) ? BLINK
| INVERS
: INVERS
);
494 LcdFlags attr
= (menuVerticalPosition
== k
? blink
: 0);
496 case ITEM_SCREEN_SETUP_THEME
: {
497 lcdDrawText(MENUS_MARGIN_LEFT
, y
+ FH
/ 2, STR_THEME
);
498 Theme
* new_theme
= editThemeChoice
<Theme
>(SCREENS_SETUP_2ND_COLUMN
, y
, getRegisteredThemes(), theme
, needsOffsetCheck
, attr
, event
);
501 loadTheme(new_theme
);
502 strncpy(g_eeGeneral
.themeName
, new_theme
->getName(), sizeof(g_eeGeneral
.themeName
));
503 killEvents(KEY_ENTER
);
504 storageDirty(EE_GENERAL
);
509 case ITEM_SCREEN_SETUP_THEME
+1:
514 uint8_t index
= k
- ITEM_SCREEN_SETUP_THEME_OPTION1
;
515 if (index
< optionsCount
) {
516 const ZoneOption
* option
= &options
[index
];
517 ZoneOptionValue
* value
= theme
->getOptionValue(index
);
518 if (editZoneOption(y
, option
, value
, attr
, EE_GENERAL
, event
)) {
522 else if (index
== optionsCount
) {
523 lcdDrawText(MENUS_MARGIN_LEFT
, y
, STR_TOP_BAR
);
524 drawButton(SCREENS_SETUP_2ND_COLUMN
, y
, STR_SETUP
, attr
);
525 if (attr
&& event
== EVT_KEY_FIRST(KEY_ENTER
)) {
526 currentScreen
= customScreens
[0];
527 currentContainer
= topbar
;
528 pushMenu(menuWidgetsSetup
);
539 enum MenuScreenSetupItems
{
540 ITEM_SCREEN_SETUP_LAYOUT
,
541 ITEM_SCREEN_SETUP_WIDGETS_SETUP
= ITEM_SCREEN_SETUP_LAYOUT
+2,
542 ITEM_SCREEN_SETUP_LAYOUT_OPTION1
,
545 bool menuScreenSetup(int index
, event_t event
)
547 if (customScreens
[index
] == NULL
) {
548 return menuScreenAdd(event
);
551 currentScreen
= customScreens
[index
];
552 currentContainer
= currentScreen
;
553 bool needsOffsetCheck
= (menuVerticalPosition
!= 0 || menuHorizontalPosition
< 0);
555 char title
[] = "Main view X";
556 title
[sizeof(title
)-2] = '1' + index
;
557 menuPageCount
= updateMainviewsMenu();
559 const ZoneOption
* options
= currentScreen
->getFactory()->getOptions();
560 int optionsCount
= getOptionsCount(options
);
561 linesCount
= ITEM_SCREEN_SETUP_LAYOUT_OPTION1
+ optionsCount
;
562 if (menuPageCount
> 3)
565 uint8_t mstate_tab
[2 + MAX_LAYOUT_OPTIONS
+ 1] = { uint8_t(NAVIGATION_LINE_BY_LINE
| uint8_t(getRegisteredLayouts().size()-1)), ORPHAN_ROW
};
566 for (int i
=0; i
<optionsCount
; i
++) {
567 mstate_tab
[3+i
] = getZoneOptionColumns(&options
[i
]);
569 mstate_tab
[3+optionsCount
] = 0; // The remove button
571 CUSTOM_MENU_WITH_OPTIONS(title
, THEME_ICONS
, menuTabScreensSetup
, menuPageCount
, index
+1, linesCount
);
573 for (int i
=0; i
<NUM_BODY_LINES
; i
++) {
574 coord_t y
= MENU_CONTENT_TOP
+ i
* FH
;
575 int k
= i
+ menuVerticalOffset
;
576 LcdFlags blink
= ((s_editMode
>0) ? BLINK
|INVERS
: INVERS
);
577 LcdFlags attr
= (menuVerticalPosition
== k
? blink
: 0);
579 case ITEM_SCREEN_SETUP_LAYOUT
:
581 lcdDrawText(MENUS_MARGIN_LEFT
, y
+ FH
/ 2, STR_LAYOUT
);
582 const LayoutFactory
* factory
= editThemeChoice
<const LayoutFactory
>(SCREENS_SETUP_2ND_COLUMN
, y
, getRegisteredLayouts(), currentScreen
->getFactory(), needsOffsetCheck
, attr
, event
);
584 delete customScreens
[index
];
585 currentScreen
= customScreens
[index
] = factory
->create(&g_model
.screenData
[index
].layoutData
);
586 strncpy(g_model
.screenData
[index
].layoutName
, factory
->getName(), sizeof(g_model
.screenData
[index
].layoutName
));
587 killEvents(KEY_ENTER
);
588 storageDirty(EE_MODEL
);
593 case ITEM_SCREEN_SETUP_LAYOUT
+1:
596 case ITEM_SCREEN_SETUP_WIDGETS_SETUP
:
597 drawButton(SCREENS_SETUP_2ND_COLUMN
, y
, STR_SETUP_WIDGETS
, attr
);
598 if (attr
&& event
== EVT_KEY_FIRST(KEY_ENTER
)) {
599 pushMenu(menuWidgetsSetup
);
605 uint8_t o
= k
- ITEM_SCREEN_SETUP_LAYOUT_OPTION1
;
606 if (o
< optionsCount
) {
607 const ZoneOption
* option
= &options
[o
];
608 ZoneOptionValue
* value
= currentScreen
->getOptionValue(o
);
609 if (editZoneOption(y
, option
, value
, attr
, EE_MODEL
, event
)) {
610 currentScreen
->update();
613 else if (menuPageCount
> 3 && o
== optionsCount
) {
614 drawButton(SCREENS_SETUP_2ND_COLUMN
, y
, STR_REMOVE_SCREEN
, attr
);
615 if (attr
&& event
== EVT_KEY_LONG(KEY_ENTER
)) {
616 delete currentScreen
;
617 if (index
!= MAX_CUSTOM_SCREENS
-1) {
618 memmove(&g_model
.screenData
[index
], &g_model
.screenData
[index
+ 1], sizeof(CustomScreenData
) * (MAX_CUSTOM_SCREENS
- index
- 1));
619 memmove(&customScreens
[index
], &customScreens
[index
+ 1], sizeof(Layout
*) * (MAX_CUSTOM_SCREENS
- index
- 1));
621 memset(&g_model
.screenData
[MAX_CUSTOM_SCREENS
-1], 0, sizeof(CustomScreenData
));
622 customScreens
[MAX_CUSTOM_SCREENS
-1] = NULL
;
624 killEvents(KEY_ENTER
);
625 chainMenu(menuTabScreensSetup
[index
> 0 ? index
: 1]);
638 bool menuCustomScreenSetup(event_t event
)
640 return menuScreenSetup(N
, event
);
643 const MenuHandlerFunc menuTabScreensSetup
[1+MAX_CUSTOM_SCREENS
] = {
645 menuCustomScreenSetup
<0>,
646 menuCustomScreenSetup
<1>,
647 menuCustomScreenSetup
<2>,
648 menuCustomScreenSetup
<3>,
649 menuCustomScreenSetup
<4>
652 int updateMainviewsMenu()
654 for (int index
=1; index
<MAX_CUSTOM_SCREENS
; index
++) {
655 if (customScreens
[index
]) {
656 THEME_ICONS
[2+index
] = ICON_THEME_VIEW1
+index
;
659 THEME_ICONS
[2+index
] = ICON_THEME_ADD_VIEW
;
663 return 1+MAX_CUSTOM_SCREENS
;
666 bool menuScreenAdd(event_t event
)
668 menuPageCount
= updateMainviewsMenu();
670 if (event
== EVT_KEY_FIRST(KEY_ENTER
) && getRegisteredLayouts().size()) {
671 const LayoutFactory
* lf
= getRegisteredLayouts().front();
672 customScreens
[menuPageCount
-2] = lf
->create(&g_model
.screenData
[menuPageCount
-2].layoutData
);
673 strncpy(g_model
.screenData
[menuPageCount
-2].layoutName
, lf
->getName(), sizeof(g_model
.screenData
[menuPageCount
-2].layoutName
));
675 menuHorizontalPosition
= -1;
676 killEvents(KEY_ENTER
);
677 storageDirty(EE_MODEL
);
681 SIMPLE_MENU_WITH_OPTIONS(STR_ADDMAINVIEW
, THEME_ICONS
, menuTabScreensSetup
, menuPageCount
, menuPageCount
-1, 0);