diff --git a/ChangeLog b/ChangeLog index 3f681632..8ca5048c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2015-06-18 Markus Gans + * Add multiple lines support for FLabel + 2015-06-12 Markus Gans * Improve focusFirstChild() and focusLastChild() diff --git a/doc/TODO b/doc/TODO index c1d7e575..89c29e4d 100644 --- a/doc/TODO +++ b/doc/TODO @@ -20,7 +20,6 @@ Missing Features └──► tmp --------------------------------------- -- Multiple lines support for FLabel - Add a window switcher on the right side of the status bar - Add a scrolling area with on-demand scroll bars for FButtonGroup diff --git a/src/flabel.cpp b/src/flabel.cpp index 3ee650c5..112e31ef 100644 --- a/src/flabel.cpp +++ b/src/flabel.cpp @@ -37,8 +37,8 @@ void FLabel::init() { flags = 0; emphasis = 0; - xoffset = 0; alignment = fc::alignLeft; + multiline = false; this->text = ""; accel_widget = 0; @@ -70,6 +70,27 @@ uChar FLabel::getHotkey() return 0; } +//---------------------------------------------------------------------- +int FLabel::getHotkeyPos(wchar_t*& src, wchar_t*& dest, uInt length) +{ + // find hotkey position in string + // + generate a new string without the '&'-sign + int hotkeypos = -1; + wchar_t* txt = src; + + for (uInt i=0; i < length; i++) + { + if ( (i < length) && (txt[i] == L'&') && (hotkeypos == -1) ) + { + hotkeypos = int(i); + i++; + src++; + } + *dest++ = *src++; + } + return hotkeypos; +} + //---------------------------------------------------------------------- void FLabel::setHotkeyAccelerator() { @@ -91,56 +112,40 @@ void FLabel::setHotkeyAccelerator() } //---------------------------------------------------------------------- -void FLabel::draw() +int FLabel::getXOffset(int length) { - register wchar_t* src; - register wchar_t* dest; - wchar_t* LabelText; - FString txt; - uInt length; - int hotkeypos, to_char; + switch ( alignment ) + { + case fc::alignLeft: + return 0; + + case fc::alignCenter: + if ( length < width ) + return int((width - length) / 2); + else + return 0; + + case fc::alignRight: + if ( length < width ) + return width - length; + else + return 0; + } + return 0; +} + +//---------------------------------------------------------------------- +void FLabel::printLine ( wchar_t*& line, + uInt length, + int hotkeypos, + int xoffset) +{ + int to_char; bool isActive, isNoUnderline; - if ( text.isNull() || text.isEmpty() ) - return; - - if ( Encoding == fc::VT100 ) - unsetVT100altChar(); - - setUpdateVTerm(false); - if ( hasEmphasis() ) - setColor (emphasis_color, backgroundColor); - else - setColor (foregroundColor, backgroundColor); - - length = text.getLength(); - hotkeypos = -1; - LabelText = new wchar_t[length+1]; - txt = this->text; - src = const_cast(txt.wc_str()); - dest = const_cast(LabelText); - isActive = ((flags & ACTIVE) != 0); isNoUnderline = ((flags & NO_UNDERLINE) != 0); - // find hotkey position in string - // + generate a new string without the '&'-sign - for (uInt i=0; i < length; i++) - { - if ( (i < length) && (txt[i] == '&') && (hotkeypos == -1) ) - { - hotkeypos = int(i); - i++; - src++; - } - *dest++ = *src++; - } - - if ( hotkeypos != -1 ) - length--; - - gotoxy (xpos+xmin-1, ypos+ymin-1); - for (int x=0; x < xoffset; x++) print (' '); @@ -154,12 +159,14 @@ void FLabel::draw() for (int z=0; z < to_char; z++) { + if ( ! iswprint(wint_t(line[z])) ) + line[z] = L' '; if ( (z == hotkeypos) && isActive ) { setColor (wc.label_hotkey_fg, wc.label_hotkey_bg); if ( ! isNoUnderline ) setUnderline(); - print ( LabelText[z] ); + print ( line[z] ); if ( ! isNoUnderline ) unsetUnderline(); if ( hasEmphasis() ) @@ -168,22 +175,105 @@ void FLabel::draw() setColor (foregroundColor, backgroundColor); } else - print ( LabelText[z] ); + print ( line[z] ); } - for (int x=to_char+2; x < width; x++) - print (' '); - if ( length > uInt(width) ) { setColor (ellipsis_color, backgroundColor); print (".."); + setColor (foregroundColor, backgroundColor); } + else + { + for (int x=xoffset+to_char; x < width; x++) + print (' '); + } + if ( hasReverseMode() ) setReverse(false); +} +//---------------------------------------------------------------------- +void FLabel::draw() +{ + wchar_t* src; + wchar_t* dest; + wchar_t* LabelText; + uInt length; + int hotkeypos, xoffset; + + if ( text.isNull() || text.isEmpty() ) + return; + + if ( Encoding == fc::VT100 ) + unsetVT100altChar(); + + setUpdateVTerm(false); + + if ( hasEmphasis() ) + setColor (emphasis_color, backgroundColor); + else + setColor (foregroundColor, backgroundColor); + + hotkeypos = -1; + + if ( multiline && height > 1 ) + { + uInt y = 0; + uInt text_lines = uInt(multiline_text.size()); + bool hotkey_printed = false; + + while ( y < text_lines && y < uInt(height) ) + { + length = multiline_text[y].getLength(); + LabelText = new wchar_t[length+1]; + + if ( ! hotkey_printed ) + { + src = const_cast(multiline_text[y].wc_str()); + dest = const_cast(LabelText); + hotkeypos = getHotkeyPos(src, dest, length); + } + else + LabelText = const_cast(multiline_text[y].wc_str()); + + gotoxy (xpos+xmin-1, ypos+ymin-1+int(y)); + + if ( hotkeypos != -1 ) + { + xoffset = getXOffset (int(length-1)); + printLine (LabelText, length-1, hotkeypos, xoffset); + hotkey_printed = true; + hotkeypos = -1; + } + else + { + xoffset = getXOffset (int(length)); + printLine (LabelText, length, -1, xoffset); + } + y++; + delete[] LabelText; + } + } + else + { + length = text.getLength(); + LabelText = new wchar_t[length+1]; + src = const_cast(text.wc_str()); + dest = const_cast(LabelText); + + hotkeypos = getHotkeyPos (src, dest, length); + + if ( hotkeypos != -1 ) + length--; + + gotoxy (xpos+xmin-1, ypos+ymin-1); + xoffset = getXOffset (int(length)); + printLine (LabelText, length, hotkeypos, xoffset); + delete[] LabelText; + } setUpdateVTerm(true); - delete[] LabelText; } @@ -284,35 +374,12 @@ void FLabel::setAccelWidget (FWidget* widget) //---------------------------------------------------------------------- void FLabel::setAlignment (uInt align) { - int text_length; - if ( align != fc::alignLeft && align != fc::alignCenter && align != fc::alignRight ) alignment = fc::alignLeft; else alignment = align; - - text_length = int(text.getLength()); - - if ( getHotkey() ) - text_length--; - - if ( text_length > width ) - text_length = width; - - switch ( alignment ) - { // convert type to msg string - case fc::alignLeft: - xoffset = 0; - break; - case fc::alignCenter: - xoffset = int((width - text_length) / 2); - break; - case fc::alignRight: - xoffset = width - text_length; - break; - } } //---------------------------------------------------------------------- @@ -361,6 +428,12 @@ void FLabel::setNumber (long num) void FLabel::setText (const FString& txt) { this->text = txt; + this->multiline_text = text.split("\r\n"); + if ( int(multiline_text.size()) > 1 ) + multiline = true; + else + multiline = false; + if ( isEnabled() ) { delAccelerator (this); diff --git a/src/flabel.h b/src/flabel.h index 8004683b..ce67d2f5 100644 --- a/src/flabel.h +++ b/src/flabel.h @@ -20,9 +20,10 @@ class FLabel : public FWidget { private: + std::vector multiline_text; + bool multiline; FString text; int emphasis; - int xoffset; uInt alignment; uChar emphasis_color; uChar ellipsis_color; @@ -35,7 +36,10 @@ class FLabel : public FWidget void init(); uChar getHotkey(); + int getHotkeyPos (wchar_t*&, wchar_t*&, uInt); void setHotkeyAccelerator(); + int getXOffset(int); + void printLine (wchar_t*&, uInt, int, int xoffset=0); void draw(); public: diff --git a/test/dialog.cpp b/test/dialog.cpp index 1680d99f..aeb2f8f9 100644 --- a/test/dialog.cpp +++ b/test/dialog.cpp @@ -33,24 +33,19 @@ int main (int argc, char* argv[]) // Create text labels FLabel label_1(&dgl), - label_2(&dgl), - label_3(&dgl), - label_4(&dgl), - label_5(&dgl); + label_2(&dgl); - label_1.setText (wchar_t(fc::BlackUpPointingTriangle)); - label_2.setText (wchar_t(fc::BoxDrawingsUpAndRight) + label_1.setText ( wchar_t(fc::BlackUpPointingTriangle) + + std::wstring(L"\n") + + wchar_t(fc::BoxDrawingsUpAndRight) + FString(2, wchar_t(fc::BoxDrawingsHorizontal)) - + FString(" Double click the title bar button,") ); - label_3.setText ("press Q on the keyboard,"); - label_4.setText ("or push the button below to exit"); - label_5.setText ("the program."); + + " Double click the title bar button," ); + label_2.setText ( "press Q on the keyboard,\n" + "or push the button below to exit\n" + "the program." ); - label_1.setGeometry (1, 1, 1, 1); - label_2.setGeometry (1, 2, 38, 1); - label_3.setGeometry (5, 3, 24, 1); - label_4.setGeometry (5, 4, 32, 1); - label_5.setGeometry (5, 5, 12, 1); + label_1.setGeometry (1, 1, 38, 2); + label_2.setGeometry (5, 3, 34, 3); // Create the quit button FButton btn("&Quit", &dgl); diff --git a/test/ui.cpp b/test/ui.cpp index 65c71067..4dbd7245 100644 --- a/test/ui.cpp +++ b/test/ui.cpp @@ -286,12 +286,12 @@ MyDialog::MyDialog (FWidget* parent) : FDialog(parent) tagged_count->setGeometry(28, 4, 5, 1); tagged_count->setNumber(0); - FLabel* sum = new FLabel(L"Sum:\n123\n456", this); - sum->setGeometry(20, 5, 7, 1); + FLabel* sum = new FLabel(L"Sum:", this); + sum->setGeometry(20, 5, 7, 3); sum->setAlignment(fc::alignRight); FLabel* sum_count = new FLabel(this); - sum_count->setGeometry(28, 5, 5, 1); + sum_count->setGeometry(28, 5, 5, 3); sum_count->setNumber(myList->count()); FStatusBar* statusbar = new FStatusBar(this);