{
16 | public StringMenuState(MenuItem item, boolean changed, boolean active, String value) {
17 | super(StateStorageType.STRING, item, changed, active, value);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/domain/util/MenuItemFormatException.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.domain.util;
2 |
3 | /**
4 | * This exception indicates that a particular item could not be formatted
5 | */
6 | public class MenuItemFormatException extends Exception{
7 | public MenuItemFormatException(String message) {
8 | super(message);
9 | }
10 |
11 | public MenuItemFormatException(String message, Throwable cause) {
12 | super(message, cause);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/mgr/DialogShowMode.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.mgr;
2 |
3 | /**
4 | * Indicates how the dialog should be shown
5 | */
6 | public enum DialogShowMode {
7 | /** Show the dialog in a regular way */
8 | REGULAR,
9 | /** The dialog is local to the delegate function provided, no remote messages will send upon action */
10 | LOCAL_TO_DELEGATE,
11 | /** The dialog is both local to the delegate and locked so cannot be replaced with another */
12 | LOCAL_DELEGATE_LOCKED
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/mgr/EmptyDialogManager.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.mgr;
2 |
3 | /**
4 | * A no-operation implementation of menu item that meets the interface but does nothing.
5 | */
6 | public class EmptyDialogManager extends DialogManager {
7 | @Override
8 | protected void dialogDidChange() {
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/mgr/MenuTreeStructureChangeListener.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.mgr;
2 |
3 | import com.thecoderscorner.menu.domain.MenuItem;
4 |
5 | /**
6 | * Indicates that there has been a structural change in the list, for example addition or removal of a menu item
7 | * in the tree. You normally subscribe to this from MenuManagerServer
8 | * @see MenuManagerServer
9 | */
10 | @FunctionalInterface
11 | public interface MenuTreeStructureChangeListener {
12 | /**
13 | * The tree has structurally changed.
14 | * @param parentHint a hint as to where the change occurred.
15 | */
16 | void treeStructureChanged(MenuItem parentHint);
17 | }
18 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/mgr/NewServerConnectionListener.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.mgr;
2 |
3 | /**
4 | * when you implement this interface and pass that instance to start on a ServerConnectionManager then you'll receive
5 | * an event for each new connection created.
6 | */
7 | public interface NewServerConnectionListener {
8 | void connectionCreated(ServerConnection connection);
9 | }
10 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/mgr/NoDialogFacilities.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.mgr;
2 |
3 | import com.thecoderscorner.menu.remote.commands.DialogMode;
4 | import com.thecoderscorner.menu.remote.commands.MenuButtonType;
5 |
6 | public class NoDialogFacilities extends DialogManager {
7 | @Override
8 | protected void dialogDidChange() {
9 | synchronized (lock) {
10 | if(mode == DialogMode.SHOW) {
11 | buttonWasPressed(button1 == MenuButtonType.NONE ? button2 : button1);
12 | }
13 | }
14 | }
15 |
16 | @Override
17 | protected void buttonWasPressed(MenuButtonType btn) {
18 | if(delegate != null) delegate.apply(btn);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/mgr/ScrollChoiceValueRetriever.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.mgr;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | /**
9 | * Marks a method as being responsible for providing the value of a particular value in a scroll choice. Each time
10 | * a scroll choice item changes, the callback associated with it is called back. In this call-back the menu item
11 | * and row number are provided. It is then your responsibility to provide the value at that location.
12 | *
13 | *
14 | * @ScrollChoiceValueRetriever(id=3)
15 | * public String myScrollChoiceNeedsValue(ScrollChoiceMenuItem item, CurrentScrollPosition position) {
16 | * return "position" + position.getPosition();
17 | * }
18 | *
19 | */
20 | @Retention(RetentionPolicy.RUNTIME)
21 | @Target(ElementType.METHOD)
22 | public @interface ScrollChoiceValueRetriever {
23 | int id();
24 | }
25 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/mgr/ServerConnectionManager.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.mgr;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * A server connection manager is responsible for connections to the menu manager, it will completely manage all the
7 | * connections, creating new ones as they come in, and removing old ones as they are closed out.
8 | */
9 | public interface ServerConnectionManager {
10 | /**
11 | * @return a list of all current connections for this manager
12 | */
13 | List getServerConnections();
14 |
15 | /**
16 | * Start the manager up so it starts to accept connections, the listener will be called for each new connection.
17 | * @param listener will receive an event when a new connection is made
18 | */
19 | void start(NewServerConnectionListener listener);
20 |
21 | /**
22 | * Stop the manager
23 | * @throws Exception if unable to stop correctly
24 | */
25 | void stop() throws Exception;
26 | }
27 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/mgr/ServerConnectionMode.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.mgr;
2 |
3 | public enum ServerConnectionMode {
4 | /** A connection that can be used only for pairing and nothing else */
5 | PAIRING,
6 | /** A connection that is not yet authenticated */
7 | UNAUTHENTICATED,
8 | /** A fully authenticated connection */
9 | AUTHENTICATED,
10 | /** The connection with the remote has been lost */
11 | DISCONNECTED
12 | }
13 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/persist/MenuStateSerialiser.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.persist;
2 |
3 | import com.thecoderscorner.menu.domain.state.AnyMenuState;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * An instance of Menu State serializer is used between runs of a local java application to load and save the state
9 | * of any menu item that has the EEPROM field set to anything other than -1. It will generally be configured with
10 | * a menu tree that will be used as the source of state data.
11 | */
12 | public interface MenuStateSerialiser {
13 | /**
14 | * load back all states from the storage and apply them all to the tree, after this all items in the tree will
15 | * contain the updated value.
16 | */
17 | void loadMenuStatesAndApply();
18 |
19 | /**
20 | * load the menu states but do not apply them to the tree
21 | * @return the list of states loaded from storage
22 | */
23 | List loadMenuStates();
24 |
25 | /**
26 | * Save the latest state of the tree into storage.
27 | */
28 | void saveMenuStates();
29 | }
30 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/persist/ReleaseType.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.persist;
2 |
3 | /**
4 | * Describes the quality of a release, such as Stable, Beta or an old build.
5 | */
6 | public enum ReleaseType { STABLE, BETA, PREVIOUS, PATCH }
7 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/AuthStatus.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote;
8 |
9 | /**
10 | * the authentication states that a RemoteMenuController can be in. Internally, the controller object is always in
11 | * one of these states, and this is just the exterior view of the state.
12 | */
13 | public enum AuthStatus {
14 | NOT_STARTED("Not yet started, or stopped"),
15 | AWAITING_CONNECTION("Waiting for connection"),
16 | ESTABLISHED_CONNECTION("Connection established"),
17 | SEND_AUTH("Send Authentication"),
18 | AUTHENTICATED("Authenticated"),
19 | FAILED_AUTH("Authentication failed"),
20 | BOOTSTRAPPING("Bootstrap Started"),
21 | CONNECTION_READY("Connection Ready"),
22 | CONNECTION_FAILED("Connection Failed");
23 |
24 | private final String description;
25 |
26 | AuthStatus(String description) {
27 | this.description = description;
28 | }
29 |
30 | public String getDescription() {
31 | return description;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/ConnectMode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote;
8 |
9 | /**
10 | * Connection mode indicates what kind of client to server connection has been established
11 | */
12 | public enum ConnectMode {
13 | /** A connection that is fully authenticated and can modify menus and bootstrap */
14 | FULLY_AUTHENTICATED,
15 | /** A connection that can only be used to pair with the device */
16 | PAIRING_CONNECTION
17 | }
18 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/ConnectionChangeListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote;
8 |
9 | /**
10 | * Use this interface to subscribe to connection change events, such as when the underlying connector
11 | * disconnects or reconnects with hardware.
12 | */
13 | @FunctionalInterface
14 | public interface ConnectionChangeListener {
15 | /**
16 | * Called by the connector upon state change
17 | * @param connector the connector who's state has changed
18 | * @param authStatus the current authentication status
19 | */
20 | void connectionChange(RemoteConnector connector, AuthStatus authStatus);
21 | }
22 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/LocalIdentifier.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote;
8 |
9 | import java.util.UUID;
10 |
11 | /**
12 | * a local identifier holder object that holds the name and UUID
13 | */
14 | public class LocalIdentifier {
15 | private final UUID uuid;
16 | private final String name;
17 |
18 | public LocalIdentifier(UUID uuid, String name) {
19 | this.uuid = uuid;
20 | this.name = name;
21 | }
22 |
23 | public UUID getUuid() {
24 | return uuid;
25 | }
26 |
27 | public String getName() {
28 | return name;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/NamedDaemonThreadFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote;
8 |
9 | import java.util.concurrent.ThreadFactory;
10 |
11 | /**
12 | * this thread factory provides better naming for threads
13 | */
14 | public class NamedDaemonThreadFactory implements ThreadFactory {
15 | private final String name;
16 |
17 | public NamedDaemonThreadFactory(String name) {
18 | this.name = name;
19 | }
20 |
21 | @Override
22 | public Thread newThread(Runnable r) {
23 | Thread th = new Thread(r);
24 | th.setDaemon(true);
25 | th.setName(name);
26 | return th;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/RemoteConnectorListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote;
8 |
9 | import com.thecoderscorner.menu.remote.commands.MenuCommand;
10 |
11 | /**
12 | * This is the low level, communication listener interface that you implement in order to know when commands have
13 | * been received from the remote device. Normally, this is used by the RemoteMenuController and not something a
14 | * user would directly subscribe to (unless you are adding custom messages to the protocol).
15 | */
16 | @FunctionalInterface
17 | public interface RemoteConnectorListener {
18 | /**
19 | * Sent by the connector when a message has been decoded.
20 | * @param connector the connector that sent the message
21 | * @param command the command it decoded.
22 | */
23 | void onCommand(RemoteConnector connector, MenuCommand command);
24 | }
25 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/RemoteDevice.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.remote;
2 |
3 | /**
4 | * This describes a remote connection at its most basic level, just the user that is connected and the name of the
5 | * connection, no other operations are supported at this level, but it provides a means of dealing with any type of
6 | * remote connection, be it acting as a server or acting as a client.
7 | */
8 | public interface RemoteDevice {
9 | String getUserName();
10 | String getConnectionName();
11 | }
12 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/commands/DialogMode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.commands;
8 |
9 | /**
10 | * The modes that a dialog can be in, and the transmission type for action too
11 | */
12 | public enum DialogMode {
13 | /** the dialog is to be shown */
14 | SHOW,
15 | /** the dialog is to be hidden */
16 | HIDE,
17 | /** perform the following action on the dialog */
18 | ACTION
19 | }
20 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/commands/MenuActionBootCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.commands;
8 |
9 | import com.thecoderscorner.menu.domain.ActionMenuItem;
10 | import com.thecoderscorner.menu.domain.state.AnyMenuState;
11 | import com.thecoderscorner.menu.domain.util.MenuItemHelper;
12 | import com.thecoderscorner.menu.remote.protocol.MessageField;
13 |
14 | public class MenuActionBootCommand extends BootItemMenuCommand {
15 | public MenuActionBootCommand(int subMenuId, ActionMenuItem menuItem, Boolean currentVal) {
16 | super(subMenuId, menuItem, currentVal);
17 | }
18 |
19 | @Override
20 | public MessageField getCommandType() {
21 | return MenuCommandType.ACTION_BOOT_ITEM;
22 | }
23 |
24 | @Override
25 | public AnyMenuState internalNewMenuState(AnyMenuState oldState) {
26 | boolean changed = !(oldState.getValue().equals(getCurrentValue()));
27 | return MenuItemHelper.stateForMenuItem(getMenuItem(), getCurrentValue(), changed, oldState.isActive());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/commands/MenuAnalogBootCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.commands;
8 |
9 | import com.thecoderscorner.menu.domain.AnalogMenuItem;
10 | import com.thecoderscorner.menu.domain.state.AnyMenuState;
11 | import com.thecoderscorner.menu.domain.util.MenuItemHelper;
12 | import com.thecoderscorner.menu.remote.protocol.MessageField;
13 |
14 | public class MenuAnalogBootCommand extends BootItemMenuCommand {
15 |
16 | public MenuAnalogBootCommand(int subMenuId, AnalogMenuItem menuItem, int currentVal) {
17 | super(subMenuId, menuItem, currentVal);
18 | }
19 |
20 | @Override
21 | public MessageField getCommandType() {
22 | return MenuCommandType.ANALOG_BOOT_ITEM;
23 | }
24 |
25 | @Override
26 | public AnyMenuState internalNewMenuState(AnyMenuState oldState) {
27 | boolean changed = !(oldState.getValue().equals(getCurrentValue()));
28 | return MenuItemHelper.stateForMenuItem(getMenuItem(), getCurrentValue(), changed, oldState.isActive());
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/commands/MenuBooleanBootCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.commands;
8 |
9 | import com.thecoderscorner.menu.domain.BooleanMenuItem;
10 | import com.thecoderscorner.menu.domain.state.AnyMenuState;
11 | import com.thecoderscorner.menu.domain.state.MenuState;
12 | import com.thecoderscorner.menu.domain.util.MenuItemHelper;
13 | import com.thecoderscorner.menu.remote.protocol.MessageField;
14 |
15 | public class MenuBooleanBootCommand extends BootItemMenuCommand {
16 |
17 | public MenuBooleanBootCommand(int subMenuId, BooleanMenuItem menuItem, boolean currentVal) {
18 | super(subMenuId, menuItem, currentVal);
19 | }
20 |
21 | @Override
22 | public MessageField getCommandType() {
23 | return MenuCommandType.BOOLEAN_BOOT_ITEM;
24 | }
25 |
26 | @Override
27 | public AnyMenuState internalNewMenuState(AnyMenuState oldState) {
28 | boolean changed = !(oldState.getValue().equals(getCurrentValue()));
29 | return MenuItemHelper.stateForMenuItem(getMenuItem(), getCurrentValue(), changed, oldState.isActive());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/commands/MenuButtonType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.commands;
8 |
9 | /**
10 | * The button type for a dialog, dialogs generally have up to two buttons by default, each button can be one of the
11 | * following types.
12 | */
13 | public enum MenuButtonType {
14 | /** The OK button */
15 | OK(0, "OK"),
16 | /** The accept button */
17 | ACCEPT(1, "Accept"),
18 | /** The cancel button */
19 | CANCEL(2, "Cancel"),
20 | /** The close button */
21 | CLOSE(3, "Close"),
22 | /** No button */
23 | NONE(4, "");
24 |
25 | private final int typeVal;
26 | private final String buttonName;
27 |
28 | MenuButtonType(int typeVal, String str) {
29 | this.typeVal = typeVal;
30 | this.buttonName = str;
31 | }
32 |
33 | public String getButtonName() {
34 | return buttonName;
35 | }
36 |
37 | public int getTypeVal() {
38 | return typeVal;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/commands/MenuCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.commands;
8 |
9 | import com.thecoderscorner.menu.remote.protocol.MessageField;
10 |
11 | /**
12 | * Classes extending from MenuCommand can be sent and received on a connector. They are protocol
13 | * neutral so as to make replacing the protocol as easy as possible.
14 | */
15 | public interface MenuCommand {
16 | /**
17 | * The type of message received.
18 | * @return the command type
19 | */
20 | MessageField getCommandType();
21 | }
22 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/commands/MenuEnumBootCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.commands;
8 |
9 | import com.thecoderscorner.menu.domain.EnumMenuItem;
10 | import com.thecoderscorner.menu.domain.state.AnyMenuState;
11 | import com.thecoderscorner.menu.domain.util.MenuItemHelper;
12 | import com.thecoderscorner.menu.remote.protocol.MessageField;
13 |
14 | public class MenuEnumBootCommand extends BootItemMenuCommand {
15 |
16 | public MenuEnumBootCommand(int subMenuId, EnumMenuItem menuItem, int currentVal) {
17 | super(subMenuId, menuItem, currentVal);
18 | }
19 |
20 | @Override
21 | public MessageField getCommandType() {
22 | return MenuCommandType.ENUM_BOOT_ITEM;
23 | }
24 |
25 | @Override
26 | public AnyMenuState internalNewMenuState(AnyMenuState oldState) {
27 | boolean changed = !(oldState.getValue().equals(getCurrentValue()));
28 | return MenuItemHelper.stateForMenuItem(getMenuItem(), getCurrentValue(), changed, oldState.isActive());
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/commands/MenuFloatBootCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.commands;
8 |
9 | import com.thecoderscorner.menu.domain.FloatMenuItem;
10 | import com.thecoderscorner.menu.domain.state.AnyMenuState;
11 | import com.thecoderscorner.menu.domain.util.MenuItemHelper;
12 | import com.thecoderscorner.menu.remote.protocol.MessageField;
13 |
14 | public class MenuFloatBootCommand extends BootItemMenuCommand {
15 |
16 | public MenuFloatBootCommand(int subMenuId, FloatMenuItem menuItem, Float currentVal) {
17 | super(subMenuId, menuItem, currentVal);
18 | }
19 |
20 | @Override
21 | public MessageField getCommandType() {
22 | return MenuCommandType.FLOAT_BOOT_ITEM;
23 | }
24 |
25 | @Override
26 | public AnyMenuState internalNewMenuState(AnyMenuState oldState) {
27 | boolean changed = !(oldState.getValue().equals(getCurrentValue()));
28 | return MenuItemHelper.stateForMenuItem(getMenuItem(), getCurrentValue(), changed, oldState.isActive());
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/commands/MenuRgb32BootCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.commands;
8 |
9 | import com.thecoderscorner.menu.domain.Rgb32MenuItem;
10 | import com.thecoderscorner.menu.domain.state.*;
11 | import com.thecoderscorner.menu.domain.util.MenuItemHelper;
12 | import com.thecoderscorner.menu.remote.protocol.MessageField;
13 |
14 | public class MenuRgb32BootCommand extends BootItemMenuCommand {
15 |
16 | public MenuRgb32BootCommand(int subMenuId, Rgb32MenuItem menuItem, PortableColor currentVal) {
17 | super(subMenuId, menuItem, currentVal);
18 | }
19 |
20 | @Override
21 | public MessageField getCommandType() {
22 | return MenuCommandType.BOOT_RGB_COLOR;
23 | }
24 |
25 | @Override
26 | public AnyMenuState internalNewMenuState(AnyMenuState oldState) {
27 | boolean changed = !(oldState.getValue().equals(getCurrentValue()));
28 | return MenuItemHelper.stateForMenuItem(getMenuItem(), getCurrentValue(), changed, oldState.isActive());
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/commands/MenuRuntimeListBootCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.commands;
8 |
9 | import com.thecoderscorner.menu.domain.RuntimeListMenuItem;
10 | import com.thecoderscorner.menu.domain.state.AnyMenuState;
11 | import com.thecoderscorner.menu.domain.util.MenuItemHelper;
12 | import com.thecoderscorner.menu.remote.protocol.MessageField;
13 |
14 | import java.util.List;
15 |
16 | public class MenuRuntimeListBootCommand extends BootItemMenuCommand> {
17 |
18 | public MenuRuntimeListBootCommand(int subMenuId, RuntimeListMenuItem menuItem, List currentVal) {
19 | super(subMenuId, menuItem, currentVal);
20 | }
21 |
22 | @Override
23 | public MessageField getCommandType() {
24 | return MenuCommandType.RUNTIME_LIST_BOOT;
25 | }
26 |
27 | @Override
28 | public AnyMenuState internalNewMenuState(AnyMenuState oldState) {
29 | boolean changed = !(oldState.getValue().equals(getCurrentValue()));
30 | return MenuItemHelper.stateForMenuItem(getMenuItem(), getCurrentValue(), changed, oldState.isActive());
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/commands/MenuScrollChoiceBootCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.commands;
8 |
9 | import com.thecoderscorner.menu.domain.ScrollChoiceMenuItem;
10 | import com.thecoderscorner.menu.domain.state.AnyMenuState;
11 | import com.thecoderscorner.menu.domain.state.CurrentScrollPosition;
12 | import com.thecoderscorner.menu.domain.util.MenuItemHelper;
13 | import com.thecoderscorner.menu.remote.protocol.MessageField;
14 |
15 | public class MenuScrollChoiceBootCommand extends BootItemMenuCommand {
16 |
17 | public MenuScrollChoiceBootCommand(int subMenuId, ScrollChoiceMenuItem menuItem, CurrentScrollPosition currentVal) {
18 | super(subMenuId, menuItem, currentVal);
19 | }
20 |
21 | @Override
22 | public MessageField getCommandType() {
23 | return MenuCommandType.BOOT_SCROLL_CHOICE;
24 | }
25 |
26 | @Override
27 | public AnyMenuState internalNewMenuState(AnyMenuState oldState) {
28 | boolean changed = !(oldState.getValue().equals(getCurrentValue()));
29 | return MenuItemHelper.stateForMenuItem(getMenuItem(), getCurrentValue(), changed, oldState.isActive());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/commands/MenuSubBootCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.commands;
8 |
9 | import com.thecoderscorner.menu.domain.SubMenuItem;
10 | import com.thecoderscorner.menu.domain.state.AnyMenuState;
11 | import com.thecoderscorner.menu.domain.util.MenuItemHelper;
12 | import com.thecoderscorner.menu.remote.protocol.MessageField;
13 |
14 | public class MenuSubBootCommand extends BootItemMenuCommand {
15 |
16 | public MenuSubBootCommand(int subMenuId, SubMenuItem menuItem, boolean currentVal) {
17 | super(subMenuId, menuItem, currentVal);
18 | }
19 |
20 | @Override
21 | public MessageField getCommandType() {
22 | return MenuCommandType.SUBMENU_BOOT_ITEM;
23 | }
24 |
25 | @Override
26 | public AnyMenuState internalNewMenuState(AnyMenuState oldState) {
27 | return MenuItemHelper.stateForMenuItem(getMenuItem(), getCurrentValue(), false, oldState.isActive());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/commands/MenuTextBootCommand.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.commands;
8 |
9 | import com.thecoderscorner.menu.domain.EditableTextMenuItem;
10 | import com.thecoderscorner.menu.domain.state.AnyMenuState;
11 | import com.thecoderscorner.menu.domain.util.MenuItemHelper;
12 | import com.thecoderscorner.menu.remote.protocol.MessageField;
13 |
14 | public class MenuTextBootCommand extends BootItemMenuCommand {
15 |
16 | public MenuTextBootCommand(int subMenuId, EditableTextMenuItem menuItem, String currentVal) {
17 | super(subMenuId, menuItem, currentVal);
18 | }
19 |
20 | @Override
21 | public MessageField getCommandType() {
22 | return MenuCommandType.TEXT_BOOT_ITEM;
23 | }
24 |
25 | @Override
26 | public AnyMenuState internalNewMenuState(AnyMenuState oldState) {
27 | boolean changed = !(oldState.getValue().equals(getCurrentValue()));
28 | return MenuItemHelper.stateForMenuItem(getMenuItem(), getCurrentValue(), changed, oldState.isActive());
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/encryption/AESEncryptionHandlerFactory.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.remote.encryption;
2 |
3 | public class AESEncryptionHandlerFactory implements EncryptionHandlerFactory {
4 | private final String key;
5 |
6 | public AESEncryptionHandlerFactory(String key) {
7 | this.key = key;
8 | }
9 |
10 | public ProtocolEncryptionHandler create() throws Exception {
11 | return new AESProtocolEncryptionHandler(key);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/encryption/EncryptMode.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.remote.encryption;
2 |
3 | /**
4 | * Defines the type of encryption that we want to use, presently always AES
5 | */
6 | public enum EncryptMode {
7 | AES_ENCRYPTION
8 | }
9 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/encryption/EncryptionHandlerFactory.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.remote.encryption;
2 |
3 | public interface EncryptionHandlerFactory {
4 | ProtocolEncryptionHandler create() throws Exception;
5 | }
6 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/encryption/NoEncryptionHandlerFactory.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.remote.encryption;
2 |
3 | public class NoEncryptionHandlerFactory implements EncryptionHandlerFactory {
4 | public ProtocolEncryptionHandler create() throws Exception {
5 | return null;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/protocol/ApiPlatform.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.protocol;
8 |
9 | /**
10 | * Provides a list of the support platforms as an enumeration. Used during joining to indicate the platform
11 | * of the connectee.
12 | */
13 | public enum ApiPlatform {
14 | ARDUINO(0, "Arduino 8-bit"),
15 | ARDUINO32(2, "Arduino 32-bit"),
16 | JAVA_API(1, "Java API"),
17 | DNET_API(3, "Arduino 32-bit"),
18 | JAVASCRIPT_CLIENT(4, "JS API");
19 |
20 | private final int key;
21 | private final String description;
22 |
23 | ApiPlatform(int key, String description) {
24 | this.key = key;
25 | this.description = description;
26 | }
27 |
28 | public int getKey() {
29 | return key;
30 | }
31 |
32 | public String getDescription() {
33 | return description;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/protocol/CommandProtocol.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.remote.protocol;
2 |
3 | public enum CommandProtocol {
4 | INVALID(0), TAG_VAL_PROTOCOL(1), RAW_BIN_PROTOCOL(2), TAG_VAL_ENCRYPTED_AES(0x81), RAW_BIN_ENCRYPTED_AES(0x82);
5 |
6 | private final byte protoNum;
7 |
8 | CommandProtocol(int num) {
9 | protoNum = (byte)num;
10 | }
11 |
12 | public byte getProtoNum() {
13 | return protoNum;
14 | }
15 |
16 | public static CommandProtocol fromProtocolId(byte num) {
17 | return num == 1 ? TAG_VAL_PROTOCOL : RAW_BIN_PROTOCOL;
18 | }
19 |
20 | public boolean isEncrypted() {
21 | return (protoNum & 0x80) != 0;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/protocol/ProtocolOutgoingMsgConverter.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.remote.protocol;
2 |
3 | import com.thecoderscorner.menu.remote.commands.MenuCommand;
4 |
5 | import java.nio.ByteBuffer;
6 |
7 | @FunctionalInterface
8 | public interface ProtocolOutgoingMsgConverter {
9 | void apply(B buffer, T cmd) throws TcProtocolException;
10 | }
11 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/protocol/RawProtocolIncomingMsgConverter.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.remote.protocol;
2 |
3 | import com.thecoderscorner.menu.remote.commands.MenuCommand;
4 |
5 | import java.nio.ByteBuffer;
6 |
7 | @FunctionalInterface
8 | public interface RawProtocolIncomingMsgConverter {
9 | MenuCommand apply(ByteBuffer buffer, int len) throws TcProtocolException;
10 | }
11 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/protocol/TagValProtocolIncomingMsgConverter.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.remote.protocol;
2 |
3 | import com.thecoderscorner.menu.remote.commands.MenuCommand;
4 |
5 | @FunctionalInterface
6 | public interface TagValProtocolIncomingMsgConverter {
7 | MenuCommand apply(TagValTextParser parser) throws TcProtocolException;
8 | }
9 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/protocol/TcProtocolException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.protocol;
8 |
9 | import java.io.IOException;
10 |
11 | /**
12 | * An exception that indicates a problem during protocol conversion
13 | */
14 | public class TcProtocolException extends IOException {
15 | public TcProtocolException(String message) {
16 | super(message);
17 | }
18 |
19 | public TcProtocolException(String message, Throwable cause) {
20 | super(message, cause);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/protocol/TcUnknownMessageException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.protocol;
8 |
9 | /**
10 | * An exception that indicates an unknown message was received during protocol conversion
11 | */
12 | public class TcUnknownMessageException extends TcProtocolException {
13 | public TcUnknownMessageException(String message) {
14 | super(message);
15 | }
16 |
17 | public TcUnknownMessageException(String message, Throwable cause) {
18 | super(message, cause);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/com/thecoderscorner/menu/remote/socket/SocketClientServerListener.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.remote.socket;
2 |
3 | public interface SocketClientServerListener {
4 | void onConnectionCreated(SocketClientRemoteConnector connector);
5 | void onConnectionClosed(SocketClientRemoteConnector connector);
6 | }
7 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/java/module-info.java:
--------------------------------------------------------------------------------
1 | module com.thecoderscorner.tcmenu.javaapi {
2 | requires com.google.gson;
3 | requires java.xml;
4 | exports com.thecoderscorner.menu.domain.state;
5 | exports com.thecoderscorner.menu.domain.util;
6 | exports com.thecoderscorner.menu.domain;
7 | exports com.thecoderscorner.menu.remote;
8 | exports com.thecoderscorner.menu.remote.encryption;
9 | exports com.thecoderscorner.menu.remote.states;
10 | exports com.thecoderscorner.menu.remote.commands;
11 | exports com.thecoderscorner.menu.remote.protocol;
12 | exports com.thecoderscorner.menu.remote.socket;
13 | exports com.thecoderscorner.menu.persist;
14 | exports com.thecoderscorner.menu.auth;
15 | exports com.thecoderscorner.menu.mgr;
16 | exports com.thecoderscorner.menu.remote.mgrclient;
17 |
18 | opens com.thecoderscorner.menu.domain to com.google.gson;
19 | opens com.thecoderscorner.menu.persist to com.google.gson;
20 | }
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/main/resources/japi-version.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | # This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | #
5 | #
6 |
7 | build.version=${project.version}
8 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/test/java/com/thecoderscorner/menu/domain/state/ListResponseTest.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.domain.state;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import static org.junit.jupiter.api.Assertions.*;
6 |
7 | class ListResponseTest {
8 |
9 | @Test
10 | void testListResponse() {
11 | var lr = new ListResponse(100, ListResponse.ResponseType.SELECT_ITEM);
12 | assertEquals(ListResponse.ResponseType.SELECT_ITEM, lr.getResponseType());
13 | assertEquals(100, lr.getRow());
14 |
15 | var lr2 = ListResponse.fromString("202:1").orElseThrow();
16 | assertEquals(ListResponse.ResponseType.INVOKE_ITEM, lr2.getResponseType());
17 | assertEquals(202, lr2.getRow());
18 |
19 | assertTrue(ListResponse.fromString("sldkfghkjd:2").isEmpty());
20 | assertTrue(ListResponse.fromString("sldkfghkjd").isEmpty());
21 | }
22 | }
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/test/java/com/thecoderscorner/menu/persist/NoLocaleHandlerTest.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.persist;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import java.util.Locale;
6 | import java.util.Map;
7 |
8 | import static org.junit.jupiter.api.Assertions.*;
9 |
10 | public class NoLocaleHandlerTest {
11 | @Test
12 | public void testNoLocaleCase() {
13 | var locale = new NoLocaleEnabledLocalHandler();
14 | assertFalse(locale.isLocalSupportEnabled());
15 | assertEquals(0, locale.getEnabledLocales().size());
16 | assertEquals("123", locale.getLocalSpecificEntry("123"));
17 | assertEquals(Map.of(), locale.getUnderlyingMap());
18 | assertEquals(new Locale("--"), locale.getCurrentLocale());
19 | assertThrows(IllegalArgumentException.class, () -> locale.changeLocale(Locale.FRENCH));
20 | assertThrows(IllegalArgumentException.class, () -> locale.setLocalSpecificEntry("a", "b"));
21 | locale.saveChanges(); // should do nothing.
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/test/java/com/thecoderscorner/menu/remote/protocol/BinaryDataCommand.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.remote.protocol;
2 |
3 | import com.thecoderscorner.menu.remote.commands.MenuCommand;
4 |
5 | public class BinaryDataCommand implements MenuCommand {
6 | public static final MessageField BIN_DATA_COMMAND = new MessageField('S', 'B');
7 |
8 | public byte[] binData;
9 |
10 | public BinaryDataCommand(byte[] binData) {
11 | this.binData = binData;
12 | }
13 |
14 | @Override
15 | public MessageField getCommandType() {
16 | return BIN_DATA_COMMAND;
17 | }
18 |
19 | public byte[] getBinData() {
20 | return binData;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/test/java/com/thecoderscorner/menu/remote/protocol/CorrelationIdTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2016-2019 https://www.thecoderscorner.com (Dave Cherry).
3 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory.
4 | *
5 | */
6 |
7 | package com.thecoderscorner.menu.remote.protocol;
8 |
9 | import org.junit.jupiter.api.Test;
10 |
11 | import static org.junit.jupiter.api.Assertions.assertEquals;
12 | import static org.junit.jupiter.api.Assertions.assertNotEquals;
13 |
14 | class CorrelationIdTest {
15 | @Test
16 | void testCorrelationId() {
17 | CorrelationId id = new CorrelationId();
18 | CorrelationId id2 = new CorrelationId();
19 | // make sure the counter is increasing so to be unique in same millisecond.
20 | assertNotEquals(id, id2);
21 |
22 | CorrelationId idCopy = new CorrelationId(id.toString());
23 |
24 | assertEquals(id, idCopy);
25 | }
26 | }
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/test/java/com/thecoderscorner/menu/remote/protocol/SpannerCommand.java:
--------------------------------------------------------------------------------
1 | package com.thecoderscorner.menu.remote.protocol;
2 |
3 | import com.thecoderscorner.menu.remote.commands.MenuCommand;
4 | import com.thecoderscorner.menu.remote.protocol.MessageField;
5 |
6 | public class SpannerCommand implements MenuCommand {
7 | public static final MessageField SPANNER_MSG_TYPE = new MessageField('S', 'Z');
8 |
9 | public int metricSize;
10 | public String make;
11 |
12 | public SpannerCommand(int metricSize, String make) {
13 | this.metricSize = metricSize;
14 | this.make = make;
15 | }
16 |
17 | @Override
18 | public MessageField getCommandType() {
19 | return SPANNER_MSG_TYPE;
20 | }
21 |
22 | public int getMetricSize() {
23 | return metricSize;
24 | }
25 |
26 | public String getMake() {
27 | return make;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/test/resources/auth.properties:
--------------------------------------------------------------------------------
1 | #TcMenu Auth properties
2 | #Sun Feb 13 15:25:51 GMT 2022
3 | Untitled=1df939bb-467c-42fc-b604-484dd31641e2
4 | Daves\ Amp\ Web=453eab49-d3df-4250-a39d-720b43dc9193
5 | DavesSim=e0a5ffca-bd6e-464c-b631-af7652ab4560
6 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/test/resources/testBundle/test.properties:
--------------------------------------------------------------------------------
1 | # comment at top
2 | welcome=hello
3 |
4 | # blank line above, then comment.
5 | leave=goodbye
6 |
7 |
8 | # two blank lines and comment
9 | thanks=thank you
10 |
11 | menu.5.name=Menu 5 name
12 | menu.3.enum.1=Menu 3 enum1
13 |
14 | root.only.entry=1234
15 |
16 | # and a blank entry
17 | menu.2.unit=
18 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/test/resources/testBundle/test_fr.properties:
--------------------------------------------------------------------------------
1 | # comment on line 1
2 | welcome=bonjour
3 |
4 | # comment and blank line
5 | leave=au rivoir
6 |
7 |
8 | # two blank lines and comment
9 | thanks=merci
10 |
11 | # utf8 should be maintained in the file and not lost
12 | menu.5.name=Paramètres
13 | menu.3.enum.1=Pâtes
14 |
--------------------------------------------------------------------------------
/tcMenuJavaApi/src/test/resources/testBundle/test_fr_CA.properties:
--------------------------------------------------------------------------------
1 | # comment on line 1
2 | welcome=bonjourCA
3 |
4 | # utf8 should be maintained in the file and not lost
5 | menu.5.name=Paramètres des pâtes
6 | menu.3.enum.1=Salade
7 |
--------------------------------------------------------------------------------
/tcMenuNative/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/tcMenuNative/.idea/fontGlyphGenerator.iml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/tcMenuNative/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/tcMenuNative/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/tcMenuNative/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tcMenuNative/README.md:
--------------------------------------------------------------------------------
1 | # TcMenuNative wrapper library
2 |
3 | This directory contains a small wrapper around freetype that has been tested on Windows, MacOS and also Ubuntu. It should be fairly easy to get this to compile on any platform that the underlying library supports.
4 |
5 | Once you've built a release build, it is your responsibility to test it, and that includes running TcMenu to ensure the font creator is working properly. Try importing fonts, with different unicode ranges etc. Ensure they look bit perfect.
6 |
7 | Once it is tested, replace the output DLL/DynLib/so file in the packaged directory.
8 |
9 | ## Windows
10 |
11 | Use the Visual Studio toolchain as the dependencies it creates are on nearly all Windows boxes.
12 |
13 | First you need a statically linked version of the freetype library, this is generally achieved by building the free type source with the static linking options enabled.
14 |
15 | ## MacOS
16 |
17 | Ensure XCode is installed. Beyond this the library should build in release mode with no further options
18 |
19 | ## Linux Ubuntu
20 |
21 | Ensure you have the following package installed.
22 |
23 | sudo apt-get install libfreetype6-dev
24 |
25 | Beyond this a release build should work.
--------------------------------------------------------------------------------
/tcMenuNative/fontTest/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.27)
2 | project(fontGlyphTest)
3 |
4 | set(CMAKE_CXX_STANDARD 17)
5 |
6 | add_executable(fontGlyphTest main.cpp)
7 |
8 | target_include_directories(fontGlyphTest PRIVATE ..)
9 |
10 | target_link_libraries(fontGlyphTest tcMenuNative)
11 |
--------------------------------------------------------------------------------
/tcMenuNative/library.cpp:
--------------------------------------------------------------------------------
1 | #include "library.h"
2 | #include
3 | #include "FreeFontHandler.h"
4 |
5 | FreeFontInitializer initializer;
6 |
7 | int initialiseLibrary() {
8 | return initializer.initialise();
9 | }
10 |
11 | FontHandle createFont(const char *font, FontStyle fontStyle, int size) {
12 | return initializer.createFont(font, fontStyle, size);
13 | }
14 |
15 | bool canDisplay(FontHandle fontHandle, int32_t code) {
16 | if(code == 0) return false;
17 | auto fh = initializer.fromFontHandler(fontHandle);
18 | if(fh) {
19 | return fh->isGlyphAvailable(code);
20 | } else {
21 | return false;
22 | }
23 | }
24 |
25 | int getFontGlyph(FontHandle fontHandle, int32_t code, ConvertedFontGlyph* input) {
26 | auto fh = initializer.fromFontHandler(fontHandle);
27 | if(fh) {
28 | return fh->getGlyph(code, input);
29 | } else {
30 | return -1;
31 | }
32 | }
33 |
34 | void closeFont(FontHandle fontHandle) {
35 | initializer.destroyFont(fontHandle);
36 | }
37 |
38 | void closeLibrary() {
39 | initializer.destroy();
40 | }
41 |
42 | void setPixelsPerInch(int ppi) {
43 | initializer.setDotsPerInch(ppi);
44 | }
45 |
--------------------------------------------------------------------------------
/tcMenuNative/library.h:
--------------------------------------------------------------------------------
1 | #ifndef FONTGLYPHGENERATOR_LIBRARY_H
2 | #define FONTGLYPHGENERATOR_LIBRARY_H
3 |
4 | #include
5 | extern "C" {
6 | typedef int32_t FontHandle;
7 |
8 | enum FontStyle {
9 | PLAIN = 0, BOLD = 1, ITALIC = 2, BOLD_ITALICS = 3
10 | };
11 |
12 | #ifdef _WIN32
13 | # ifdef LIBRARY_EXPORTS
14 | # define LIBRARY_API __declspec(dllexport)
15 | # else
16 | # define LIBRARY_API __declspec(dllimport)
17 | # endif
18 | #else
19 | # define LIBRARY_API
20 | #endif
21 |
22 |
23 | #define GLYPH_SIZE 2048
24 | #define MAX_ALLOWED_BIT_POS (GLYPH_SIZE * 8)
25 |
26 | struct ConvertedFontGlyph {
27 | uint8_t data[GLYPH_SIZE];
28 | int32_t code;
29 | int16_t dataSize;
30 | int16_t width;
31 | int16_t height;
32 | int16_t xAdvance;
33 | int16_t xOffset;
34 | int16_t yOffset;
35 | };
36 |
37 | LIBRARY_API int initialiseLibrary();
38 |
39 | LIBRARY_API void setPixelsPerInch(int ppi);
40 |
41 | LIBRARY_API FontHandle createFont(const char *font, FontStyle fontStyle, int size);
42 |
43 | LIBRARY_API bool canDisplay(FontHandle fontHandle, int32_t code);
44 |
45 | LIBRARY_API int getFontGlyph(FontHandle fontHandle, int32_t code, ConvertedFontGlyph* input);
46 |
47 | LIBRARY_API void closeFont(FontHandle fontHandle);
48 |
49 | LIBRARY_API void closeLibrary();
50 |
51 | };
52 | #endif //FONTGLYPHGENERATOR_LIBRARY_H
53 |
--------------------------------------------------------------------------------
/tcMenuNative/packaged/mac/libtcMenuNative.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/tcMenuNative/packaged/mac/libtcMenuNative.dylib
--------------------------------------------------------------------------------
/tcMenuNative/packaged/mac/macos.md:
--------------------------------------------------------------------------------
1 | On a Mac device the freetype and other libraries are already present so there is no need to include them, for Java development simply add this directory to your path
2 |
--------------------------------------------------------------------------------
/tcMenuNative/packaged/ubu/libtcMenuNative.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/tcMenuNative/packaged/ubu/libtcMenuNative.so
--------------------------------------------------------------------------------
/tcMenuNative/packaged/win/freetype.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/tcMenuNative/packaged/win/freetype.lib
--------------------------------------------------------------------------------
/tcMenuNative/packaged/win/tcMenuNative.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/tcMenuNative/packaged/win/tcMenuNative.dll
--------------------------------------------------------------------------------
/tcMenuNative/packaged/win/tcMenuNative.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/tcMenuNative/packaged/win/tcMenuNative.lib
--------------------------------------------------------------------------------
/tcMenuNative/packaged/win/windows.md:
--------------------------------------------------------------------------------
1 | On Windows the freetype library itself must be built from source as a static library. This will then be included in the DLL that gets created.
2 |
3 | For Java development, simply add this directory to your library path.
4 |
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/DfRobotShield.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/DfRobotShield.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/adagfx-color.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/adagfx-color.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/custom-display.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/custom-display.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/embedded-java.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/embedded-java.png
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/esp8266.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/esp8266.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/joystick.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/joystick.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/lcd-display.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/lcd-display.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/matrix-keyboard.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/matrix-keyboard.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/no-display.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/no-display.png
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/oled-display.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/oled-display.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/resistive-touch.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/resistive-touch.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/rotary-encoder.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/rotary-encoder.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/ssd1306ascii.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/ssd1306ascii.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/touch-pad-sensor.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/touch-pad-sensor.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/up-down-encoder.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/up-down-encoder.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/Images/user-button.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-display/Images/user-button.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-display/noInput.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 | %core.no.input.desc
8 |
9 |
10 | no-display.png
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/xmlPlugins/core-remote/Images/embedCONTROL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-remote/Images/embedCONTROL.png
--------------------------------------------------------------------------------
/xmlPlugins/core-remote/Images/embedCONTROLJS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-remote/Images/embedCONTROLJS.png
--------------------------------------------------------------------------------
/xmlPlugins/core-remote/Images/esp8266.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-remote/Images/esp8266.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-remote/Images/ethernet-shield.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-remote/Images/ethernet-shield.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-remote/Images/mbed-ethernet.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-remote/Images/mbed-ethernet.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-remote/Images/menu-in-menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-remote/Images/menu-in-menu.png
--------------------------------------------------------------------------------
/xmlPlugins/core-remote/Images/no-display.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-remote/Images/no-display.png
--------------------------------------------------------------------------------
/xmlPlugins/core-remote/Images/serial-connection.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-remote/Images/serial-connection.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-remote/Images/simhub.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-remote/Images/simhub.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-remote/noRemote.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 | Select this option when you don't need any remote control functionality.
8 |
9 |
10 | no-display.png
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/xmlPlugins/core-remote/serialSrc/StdioTransport.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "StdioTransport.h"
3 |
4 | int StdioTransport::writeStr(const char *data) {
5 | auto dl = strlen(data);
6 | for(size_t i = 0; i
5 | #include
6 | #include
7 | #include "SCCircularBuffer.h"
8 |
9 | namespace tcremote {
10 |
11 | class StdioTransport : public TagValueTransport {
12 | private:
13 | SCCircularBuffer inputBuffer;
14 | public:
15 | explicit StdioTransport(int readBufferSize) : inputBuffer(readBufferSize), TagValueTransport(TVAL_UNBUFFERED) {}
16 |
17 | void flush() override { stdio_flush(); }
18 |
19 | int writeChar(char data) override;
20 |
21 | int writeStr(const char *data) override;
22 |
23 | uint8_t readByte() override;
24 |
25 | bool readAvailable() override;
26 |
27 | bool available() override { return true; }
28 |
29 | bool connected() override { return true; }
30 |
31 | void close() override;
32 | };
33 | }
34 |
35 | #ifndef TC_MANUAL_NAMESPACING
36 | using namespace tcremote;
37 | #endif // TC_MANUAL_NAMESPACING
38 |
39 | #endif //STDIO_TRANSPORT_H
40 |
--------------------------------------------------------------------------------
/xmlPlugins/core-themes/Images/no-theme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-themes/Images/no-theme.png
--------------------------------------------------------------------------------
/xmlPlugins/core-themes/Images/theme-cool-blue-modern.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-themes/Images/theme-cool-blue-modern.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-themes/Images/theme-cool-blue-traditional.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-themes/Images/theme-cool-blue-traditional.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-themes/Images/theme-dark-mode-modern.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-themes/Images/theme-dark-mode-modern.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-themes/Images/theme-dark-mode-traditional.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-themes/Images/theme-dark-mode-traditional.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-themes/Images/theme-oled-bordered.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-themes/Images/theme-oled-bordered.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-themes/Images/theme-oled-inverse.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/xmlPlugins/core-themes/Images/theme-oled-inverse.jpg
--------------------------------------------------------------------------------
/xmlPlugins/core-themes/ManualTheme.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 | %theme.manual.desc
9 |
10 |
11 | no-theme.png
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/xmlPlugins/core-themes/NoThemeSelected.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 | %theme.not.required.desc
9 |
10 |
11 | no-theme.png
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/xmlPlugins/core-themes/i18n/plugin-lang_fr.properties:
--------------------------------------------------------------------------------
1 | plugin.name=Core themes plugin
2 |
--------------------------------------------------------------------------------
/xmlPlugins/examples/example-plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | 1.3.5
8 | Demo plugin
9 | This plugin shows how to write plugins.
10 |
11 |
12 |
13 |
14 |
15 | example-plugin-item.xml
16 |
17 |
--------------------------------------------------------------------------------
/xmlPlugins/xmlPlugins.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/zMedia/design-menu-for-arduino.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/zMedia/design-menu-for-arduino.jpg
--------------------------------------------------------------------------------
/zMedia/generate-code-for-your-platform.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/zMedia/generate-code-for-your-platform.jpg
--------------------------------------------------------------------------------
/zMedia/menu-on-lcd-avr.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/zMedia/menu-on-lcd-avr.jpg
--------------------------------------------------------------------------------
/zMedia/theme-cool-blue-modern.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/zMedia/theme-cool-blue-modern.jpg
--------------------------------------------------------------------------------
/zMedia/theme-dark-mode-modern.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/zMedia/theme-dark-mode-modern.jpg
--------------------------------------------------------------------------------
/zMedia/theme-oled-bordered.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TcMenu/tcMenu/c174d2ef33140aa474dd6f351a59fecf393eccbd/zMedia/theme-oled-bordered.jpg
--------------------------------------------------------------------------------