Skip to content

Commit a353ad4

Browse files
authored
Major improvements to the Embedded Raspberry PI code generator (#540)
* #537 improve custom panel support embed control * #537 documentation and a few minor updates. * #537 documentation and a few minor updates. * #537 clean up embed control code * #537 clean up embed control documentation * #538 Java project now based on the template project
1 parent 7140e47 commit a353ad4

File tree

63 files changed

+1147
-2118
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1147
-2118
lines changed

embedCONTROLCore/src/main/java/com/thecoderscorner/embedcontrol/core/controlmgr/BaseEditorComponent.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,21 @@
88

99
import java.util.Set;
1010

11-
/**
12-
* The absolute base class of editor components, this class contains many helper functions needed to be able to render
13-
* a menu item onto the display, regardless of the type of item, or display technology. This includes working out
14-
* what text needs to be displayed, handling updates including the momentary change in color on value change. Error
15-
* handling and correlation is also dealt with here.
16-
*
17-
* @param <W> The window component type
18-
*/
11+
/// This class is the base of all editor components that can represent a menu item onto a window, and as such contains
12+
/// many helper functions needed to be able to keep the control in sync with the menu item, regardless of the type of
13+
/// item, or display technology. Normally for JavaFX the generic type is `Node`.
14+
///
15+
/// In order to present a menu item onto the display, we need to work out what text needs to be displayed, what kind
16+
/// of control is capable of presenting the menu item, and handling updates including a momentary change in color on
17+
/// value change. Error handling and correlation is also dealt with here.
18+
///
19+
/// You normally create items of this class by interacting with the `MenuEditorFactory` interface. If you're trying
20+
/// to create a custom page within `EmbedControl` it is recommended to start with `BaseCustomMenuPanel` as that already
21+
/// creates everything you're likely to need, and has examples of creating controls.
22+
///
23+
/// @see MenuEditorFactory
24+
/// @see com.thecoderscorner.embedcontrol.jfx.controlmgr.panels.BaseCustomMenuPanel
25+
/// @param <W> The window component type for JavaFX it is Node.
1926
public abstract class BaseEditorComponent<W> implements EditorComponent<W> {
2027
public static final int MAX_CORRELATION_WAIT = 5000;
2128

embedCONTROLCore/src/main/java/com/thecoderscorner/embedcontrol/core/controlmgr/BaseUpDownIntEditorComponent.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
import com.thecoderscorner.menu.domain.state.MenuState;
55
import com.thecoderscorner.menu.domain.util.MenuItemFormatter;
66

7+
/// BaseUpDownIntEditorComponent is an abstract class that handles
8+
/// the core logic for an editor component with up/down integer adjustments.
9+
/// This class extends [BaseEditorComponent] and encapsulates the functionalities
10+
/// required to manage integer values.
11+
///
12+
/// @param <T> The type of the value this editor component will manage.
13+
/// @param <W> The type of the widget component.
714
public abstract class BaseUpDownIntEditorComponent<T, W> extends BaseEditorComponent<W> {
815
protected T currentVal;
916

embedCONTROLCore/src/main/java/com/thecoderscorner/embedcontrol/core/controlmgr/ComponentPositioning.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package com.thecoderscorner.embedcontrol.core.controlmgr;
22

3-
/**
4-
* Represents an abstract way of positioning menu item controls for display in a grid. Containing the row, column
5-
* and span of each.
6-
*/
3+
/// Represents an abstract way of positioning menu item controls for display in a grid. Containing the row, column
4+
/// and span of each. Generally always used with {@link ComponentSettings}
75
public class ComponentPositioning {
86
private final int row;
97
private final int col;

embedCONTROLCore/src/main/java/com/thecoderscorner/embedcontrol/core/controlmgr/ComponentSettings.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@
99
import static com.thecoderscorner.embedcontrol.core.controlmgr.RedrawingMode.SHOW_NAME_VALUE;
1010
import static com.thecoderscorner.embedcontrol.customization.MenuFormItem.FONT_100_PERCENT;
1111

12-
/**
13-
* When automatic menu layout is used, the layout is described in terms of font, color, position and justification using
14-
* this class. It can either be auto-generated on the fly, or selected by a user and serialized by the layout persister
15-
* for later reloading. This is essentially a value class.
16-
*
17-
*/
12+
/// This class describes how a menu item should be rendered onto the display. It contains the most important drawing
13+
/// settings along with grid positioning data. It also allows for conditional colouring and custom drawing. Usually
14+
/// use the {@link ComponentSettingsBuilder} in order to create an instance of this class.
15+
///
16+
/// For automatic menu layout cases, the layout is described in terms of font, color, position and justification using
17+
/// this class based on some standard defaults.
18+
///
19+
/// @see CustomDrawingConfiguration
20+
/// @see ConditionalColoring
1821
public class ComponentSettings {
1922
public static final ComponentSettings NO_COMPONENT = new ComponentSettings(new NullConditionalColoring(),
2023
FONT_100_PERCENT, PortableAlignment.LEFT, new ComponentPositioning(0, 0), SHOW_NAME_VALUE,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package com.thecoderscorner.embedcontrol.core.controlmgr;
2+
3+
import com.thecoderscorner.embedcontrol.core.controlmgr.color.ConditionalColoring;
4+
import com.thecoderscorner.embedcontrol.customization.FontInformation;
5+
import com.thecoderscorner.embedcontrol.customization.customdraw.CustomDrawingConfiguration;
6+
import com.thecoderscorner.menu.domain.*;
7+
8+
import java.util.Set;
9+
10+
import static com.thecoderscorner.embedcontrol.core.controlmgr.EditorComponent.PortableAlignment;
11+
import static com.thecoderscorner.embedcontrol.customization.MenuFormItem.FONT_100_PERCENT;
12+
13+
/**
14+
* ComponentSettingsBuilder is a builder class for creating instances of ComponentSettings.
15+
* It provides various methods to customize the settings of a component, such as font, colors,
16+
* justification, position, control type, drawing mode, and custom drawing configuration.
17+
*/
18+
public class ComponentSettingsBuilder {
19+
public enum BuildingMode { MENU, TEXT, IMAGE }
20+
21+
private final static Set<EditItemType> POSSIBLE_TIME_TYPES = Set.of(
22+
EditItemType.TIME_12H,
23+
EditItemType.TIME_24_HUNDREDS,
24+
EditItemType.TIME_24H,
25+
EditItemType.TIME_12H_HHMM,
26+
EditItemType.TIME_24H_HHMM);
27+
28+
private BuildingMode mode;
29+
private String text;
30+
private MenuItem item;
31+
private FontInformation fontInfo = FONT_100_PERCENT;
32+
private ConditionalColoring colors;
33+
private PortableAlignment justification = PortableAlignment.LEFT_VAL_RIGHT;
34+
private ComponentPositioning position = new ComponentPositioning(0, 0);
35+
private ControlType controlType = ControlType.TEXT_CONTROL;
36+
private RedrawingMode drawMode = RedrawingMode.SHOW_NAME_VALUE;
37+
private CustomDrawingConfiguration customDrawing = CustomDrawingConfiguration.NO_CUSTOM_DRAWING;
38+
39+
/// Create component settings builder object from a menu item. It defaults the fields to reasonable values as
40+
/// much as possible by setting the font to 100% size, setting the control type to the default, and setting the
41+
/// justification to the default too.
42+
/// @param item the menu item to build for
43+
/// @param color the colors to use for the control
44+
public static ComponentSettingsBuilder forMenuItem(MenuItem item, ConditionalColoring color) {
45+
var b = new ComponentSettingsBuilder();
46+
b.mode = BuildingMode.MENU;
47+
b.colors = color;
48+
b.item = item;
49+
b.withControlType(defaultControlForType(item));
50+
b.withJustification(defaultJustificationForType(b.controlType));
51+
return b;
52+
}
53+
54+
/// Create a component settings builder object that will represent some text on the display at a
55+
/// particular grid position, will default to the text color, 100% font size, and left justification.
56+
/// @param text the text to present
57+
/// @param color the color set to use
58+
public static ComponentSettingsBuilder forText(String text, ConditionalColoring color) {
59+
var b = new ComponentSettingsBuilder();
60+
b.mode = BuildingMode.TEXT;
61+
b.colors = color;
62+
b.text = text;
63+
b.withControlType(ControlType.TEXT_CONTROL);
64+
b.withJustification(PortableAlignment.LEFT);
65+
return b;
66+
}
67+
68+
private static PortableAlignment defaultJustificationForType(ControlType controlType) {
69+
return switch(controlType) {
70+
case HORIZONTAL_SLIDER, UP_DOWN_CONTROL -> PortableAlignment.LEFT_VAL_RIGHT;
71+
case BUTTON_CONTROL, VU_METER, ROTARY_METER -> PortableAlignment.CENTER;
72+
default -> PortableAlignment.LEFT;
73+
};
74+
}
75+
76+
public static ControlType defaultControlForType(MenuItem item) {
77+
return switch(item) {
78+
case SubMenuItem _, BooleanMenuItem _, ActionMenuItem _ -> ControlType.BUTTON_CONTROL;
79+
case AnalogMenuItem _ -> ControlType.HORIZONTAL_SLIDER;
80+
case EnumMenuItem _, ScrollChoiceMenuItem _ -> ControlType.UP_DOWN_CONTROL;
81+
case Rgb32MenuItem _ -> ControlType.RGB_CONTROL;
82+
case RuntimeListMenuItem _ -> ControlType.LIST_CONTROL;
83+
case CustomBuilderMenuItem _ -> ControlType.AUTH_IOT_CONTROL;
84+
case EditableTextMenuItem txt when txt.getItemType() == EditItemType.GREGORIAN_DATE -> ControlType.DATE_CONTROL;
85+
case EditableTextMenuItem txt when POSSIBLE_TIME_TYPES.contains(txt.getItemType()) -> ControlType.TIME_CONTROL;
86+
default -> ControlType.TEXT_CONTROL;
87+
};
88+
}
89+
90+
/// Override the font from the default 100% size to another value
91+
/// @param fontInfo the font to override with.
92+
public ComponentSettingsBuilder withFont(FontInformation fontInfo) {
93+
this.fontInfo = fontInfo;
94+
return this;
95+
}
96+
97+
/// Change the conditional coloring from the default one chosen.
98+
/// @param colors the conditional colors
99+
public ComponentSettingsBuilder withColors(ConditionalColoring colors) {
100+
this.colors = colors;
101+
return this;
102+
}
103+
104+
/// Change the justification from the default value which is guessed during `forMenuItem` based on the control.
105+
/// @param justification the justification to use
106+
public ComponentSettingsBuilder withJustification(PortableAlignment justification) {
107+
this.justification = justification;
108+
return this;
109+
}
110+
111+
/// Set the position of the control in the grid. Must always be set, for simpler cases with
112+
/// no span you can use `withRowCol`
113+
/// @param position the position and span in the grid to create with
114+
public ComponentSettingsBuilder withPosition(ComponentPositioning position) {
115+
this.position = position;
116+
return this;
117+
}
118+
119+
/// Set the position of the control in the grid. Must always be set
120+
/// @param row the zero based row
121+
/// @param col the zero based column
122+
public ComponentSettingsBuilder withRowCol(int row, int col) {
123+
this.position = new ComponentPositioning(row, col);
124+
return this;
125+
}
126+
127+
/// Override the control type that was guessed during `forMenuItem`. You should be careful that the control type
128+
/// you choose is compatible with the menu item type.
129+
/// @param controlType the control type to use
130+
/// @throws IllegalArgumentException if the control type is invalid for the menu item
131+
public ComponentSettingsBuilder withControlType(ControlType controlType) {
132+
if(mode != BuildingMode.MENU) {
133+
controlType = ControlType.TEXT_CONTROL;
134+
} else if(!controlType.isSupportedFor(item)) {
135+
throw new IllegalArgumentException("Control type %s cannot render %s".formatted(controlType, item.getClass().getSimpleName()));
136+
} else {
137+
this.controlType = controlType;
138+
}
139+
return this;
140+
}
141+
142+
/// Sets the drawing mode for the item, defaults to show name and item.
143+
/// @param drawMode the drawing mode
144+
public ComponentSettingsBuilder withDrawMode(RedrawingMode drawMode) {
145+
this.drawMode = drawMode;
146+
return this;
147+
}
148+
149+
/// Configure a custom drawing for the item, again make sure it is compatible with the menu type your using.
150+
/// @param customDrawing the custom drawing to be used, must be compatible with the menu item type.
151+
/// @throws IllegalArgumentException if the custom drawing is incompatible with the menu item type
152+
public ComponentSettingsBuilder withCustomDrawing(CustomDrawingConfiguration customDrawing) {
153+
if(!customDrawing.isSupportedFor(item)) {
154+
throw new IllegalArgumentException("Custom drawing %s cannot render %s".formatted(customDrawing, item.getClass().getSimpleName()));
155+
}
156+
this.customDrawing = customDrawing;
157+
return this;
158+
}
159+
160+
/// Get the menuitem for this builder
161+
/// @return menu item
162+
public MenuItem getItem() {
163+
return item;
164+
}
165+
166+
/// Get the static text associated with this builder
167+
/// @return the static text
168+
public String getText() {
169+
return text;
170+
}
171+
172+
/// Get the mode of the building, IE text, menu item etc.
173+
/// @return the building mode
174+
public BuildingMode getMode() {
175+
return mode;
176+
}
177+
178+
/// Creates the component settings
179+
/// @return the built object
180+
public ComponentSettings build() {
181+
return new ComponentSettings(colors, fontInfo, justification, position, drawMode, controlType, customDrawing, true);
182+
}
183+
}

embedCONTROLCore/src/main/java/com/thecoderscorner/embedcontrol/core/controlmgr/ControlType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import java.util.List;
66

77
/**
8-
* Represents the type of embedCONTROL control to use, these are hints to the rendering layer to help it to decide
8+
* Represents the type of Embed Control display item to use, these are hints to the rendering layer to help it to decide
99
* what to display.
1010
*/
1111
public enum ControlType {

embedCONTROLCore/src/main/java/com/thecoderscorner/embedcontrol/core/controlmgr/EditorComponent.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,19 @@
55
import com.thecoderscorner.menu.remote.commands.AckStatus;
66
import com.thecoderscorner.menu.remote.protocol.CorrelationId;
77

8-
/**
9-
* This interface represents an item that can be drawn onto a display, it does not say what the control should be
10-
* directly, the control is created by a call to createComponent, which generates the required UI node.
11-
* @param <T> the base node type for the UI
12-
*/
8+
/// This interface represents an item that can be drawn onto a display, it does not say what the control should be
9+
/// directly, the control is created by a call to createComponent, which generates the required UI node.
10+
///
11+
/// In order to present a menu item onto the display, we need to work out what text needs to be displayed, what kind
12+
/// of control is capable of presenting the menu item, and handling updates including a momentary change in color on
13+
/// value change. Error handling and correlation is also dealt with here.
14+
///
15+
/// You normally create items of this class by interacting with the `MenuEditorFactory` interface. If you're trying
16+
/// to create a custom page within `EmbedControl` it is recommended to start with `BaseCustomMenuPanel` as that already
17+
/// creates everything you're likely to need, and has examples of creating controls.
18+
///
19+
/// @see BaseEditorComponent
20+
/// @param <T> the base node type for the UI
1321
public interface EditorComponent<T> {
1422

1523
/**

embedCONTROLCore/src/main/java/com/thecoderscorner/embedcontrol/core/controlmgr/MenuComponentControl.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
import com.thecoderscorner.menu.remote.protocol.CorrelationId;
77

88
/**
9-
* embedCONTROL is used in both local and remote settings, as such there is a need for different implementations of
10-
* things such as updates, and connection handling. This interface bridges the gap between the two.
9+
* Embed Control is used in both local and remote settings, as such there is a need for different implementations of
10+
* things such as updates, and connection handling. This interface provides a way to provide a suitable implementation
11+
* for all environments.
1112
*/
1213
public interface MenuComponentControl {
1314
/**

embedCONTROLCore/src/main/java/com/thecoderscorner/embedcontrol/core/controlmgr/MenuEditorFactory.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,19 @@
66
import java.util.Optional;
77
import java.util.function.Consumer;
88

9-
/**
10-
* A menu control grid is responsible for actually placing controls onto the UI. It has a method for each type of
11-
* control that can be added, and has helper methods to clear down the grid, and to nest menu items, this allows for
12-
* cases where recursive menu rendering is used to give visual clues such as indentation.
13-
* @param <T>
14-
*/
9+
/// This factory is responsible for creating controls that can be placed into a window or screen. The default JavaFX
10+
/// implementation creates JavaFX `Node` objects for each editor component. For the standard case that you want to
11+
/// create a custom panel in Embed Control then you should most likely start with `BaseCustomMenuPanel`.
12+
///
13+
/// The factory has a method for each type of control that can be added. The `getComponentEditorItem` method takes a
14+
/// `ComponentSettings` and returns an `EditorComponent`. The editor component is kind of like a wrapper around the
15+
/// actual control, and can keep the control up-to-date and in the right state when associated with a
16+
/// [com.thecoderscorner.embedcontrol.jfx.controlmgr.panels.BaseCustomMenuPanel]. If you want to use these components
17+
/// outside of the base custom panel, then you should look at the custom panel implementation to see how to interact
18+
/// with editor components.
19+
///
20+
/// @see com.thecoderscorner.embedcontrol.jfx.controlmgr.JfxMenuEditorFactory
21+
/// @param <T> the control type
1522
public interface MenuEditorFactory<T>
1623
{
1724
/**

0 commit comments

Comments
 (0)