ArduinoMenu icon indicating copy to clipboard operation
ArduinoMenu copied to clipboard

How to align values to the right

Open ferchinas opened this issue 5 years ago • 6 comments

Hello: In "menuValues" I would like to align the text to the left and the values to the right. That's possible?

ferchinas avatar Sep 21 '19 19:09 ferchinas

yes, if you derive the field class and redefine its print function

https://github.com/neu-rah/ArduinoMenu/blob/master/src/itemsTemplates.hpp#L41

neu-rah avatar Sep 21 '19 19:09 neu-rah

Hi Rui: Sorry for the delay. I want to know the maximum number of characters for a line. To claim the amount of spaces that I must add before printing the edit symbol, value and unit.

Processor: ESP32

const byte _displayWidth = 128;
const byte _menuFontX = 9;
 
...

U8G2_SSD1306_128X64_NONAME_F_HW_I2C Display (U8G2_R0, U8X8_PIN_NONE, 21, 22);

...

MENU_OUTPUTS (out, MAX_DEPTH, U8G2_OUT (Display, colors, _menuFontX, _menuFontY, _displayOffsetX, _displayOffsetY, {0,0, _displayWidth / _menuFontX, _displayHeight / _menuFontY})
, SERIAL_OUT (Serial)
);

...
Used menuField <T> :: printTo (navRoot & root, bool sel, menuOut & out, idx_t idx, idx_t len, idx_t panelNr)

len: is the maximum number of characters on the line?

Within this function len has a value of 36 but _displayWidth / _menuFontX = 128/9 ~ "14" and not 36

Where is my confusion?

ferchinas avatar Oct 21 '19 22:10 ferchinas

len is the remaining characters on the device line (some are just not respecting it), print should stop when len=0

i will deprecate this on AM5 in favor of device specific clipping instead of that crazy and buggy parameter passing

edit: also they should return the characters remaining at line after print (Used converts/or defined as idx_t)

neu-rah avatar Oct 22 '19 16:10 neu-rah

Hi Rui: The function is working quite well. If you like it, I can share it as a plugin. If you have any suggestions to improve it before, it is very welcome!

#define _menuCantCharX 14    //Maximum number of characters in a line

template<typename T>
class menuFieldRigth :public menuField<T> {								//https://github.com/neu-rah/ArduinoMenu/blob/master/examples/customField/customField/customField.ino
private:

public:
	menuFieldRigth(constMEM menuFieldShadow<T>& shadow) :menuField<T>(shadow) {}
	menuFieldRigth(
		T& value,
		constText* text,
		constText* units,
		T low,
		T high,
		T step,
		T tune,
		action a = doNothing,
		eventMask e = noEvent,
		styles s = noStyle
	) :menuFieldRigth(*new menuFieldShadow<T>(value, text, units, low, high, step, tune, a, e, s)) {}

	Used printTo(navRoot& root, bool sel, menuOut& out, idx_t idx, idx_t len, idx_t panelNr = 0) override {
		
		idx_t l = prompt::printTo(root, sel, out, idx, len);		
		menuField<T>::reflex = menuField<T>::target();
		
		char buffer[_menuCantCharX] = "";
		String value = "";
		value += ((root.navFocus == this && sel) ? (menuField<T>::tunning ? ">" : ":") : " ");
		value += menuField<T>::reflex;
		value += fieldBase::units();
		strcat_rigth(buffer, value.c_str(), (_menuCantCharX - l) );
		out.print(buffer);		
		return(_menuCantCharX);	
	}
};


void strcat_rigth(char* dest, const char* org, byte maxChars) {
	byte orgLen = strlen(org);
	byte destLen = strlen(dest);

	while ((destLen + orgLen) < maxChars)
	{
		strcat(dest, " ");
		dest[destLen] = SPACE_CHAR;
		destLen++;
	}

	orgLen = 0;	//ahora la uso para contar los caracteres que voy escribiendo

	while ((destLen <= maxChars) && (org[orgLen] != NULL_CHAR))
	{
		dest[destLen] = org[orgLen];
		destLen++;
		orgLen++;
	}
	dest[destLen] = NULL_CHAR;
}

I encountered a problem assigning the "° C" unit because the strlen () function counts the character ´ ° ´ as two bytes. Do you know how I can fix it?

ferchinas avatar Oct 31 '19 14:10 ferchinas

@ferchinas Hi Fernando! its very welcome,please do so with a pull-request to preserve your authorship

neu-rah avatar Oct 31 '19 16:10 neu-rah

strlen () function counts the character ´ ° ´ as two bytes.

i know why and i could solve it, however solution is not elegant. Its because of extended characters surrogates. some codes imply a second character, extending the character table (ie:UTF8). We can map the surrogate codes for a specific code set, however some display libraries will also do the same (duplicate code, not elegant), u8g2 is an example, and this libraries have its own api to do just that, provide a string length in pixels or by accepting a clip rectangle that will results in same functionality. Because the purpose is to limit printing to a rectangular region. Measuring string is essential for text centering with non-monometric fonts.

not elegant but possible :D

neu-rah avatar Oct 31 '19 16:10 neu-rah