From 58371c36d3175d16e5fdc9680a2c728a0b9a9f35 Mon Sep 17 00:00:00 2001 From: Bruno Herbelin Date: Mon, 13 Nov 2023 12:41:37 +0100 Subject: [PATCH] Text source satisfying Improved layout options, better UI, tested features. --- rsc/images/icons.dds | Bin 1638528 -> 1638528 bytes src/DisplaysView.cpp | 4 +- src/GlmToolkit.h | 2 +- src/ImGuiToolkit.cpp | 26 +++++- src/ImGuiToolkit.h | 5 +- src/ImGuiVisitor.cpp | 170 +++++++++++++++++++++++++++++++---- src/Log.cpp | 2 +- src/SessionCreator.cpp | 36 ++++++-- src/SessionVisitor.cpp | 9 +- src/TextSource.cpp | 116 +++++++++++++++++++++--- src/TextSource.h | 56 ++++++++---- src/UserInterfaceManager.cpp | 12 +-- 12 files changed, 368 insertions(+), 70 deletions(-) diff --git a/rsc/images/icons.dds b/rsc/images/icons.dds index f9aafa8a338d9d453b2de2b49e19b7454a297391..4dc9e364d7d93b7a61987eb5059a6b63c335d5d4 100644 GIT binary patch delta 5067 zcmeHKeQXrR6`$EX-yV3+w|jR+Bqs41+c?C+tN|&71~7>ek}7~n>Y_?~92Kz}N(zn| zDFp<#;tqr$(e$d29(21Q%nh9qErIO2DK(Qkl-V#NkVMjbY}PV zZi5Y^AAd6Az1=r&-kbM+?_<|NZB>x|g>Z-q@gYYjC*%wXAy;TjXly9=fVg!_G{3Hq zkCS+$uL5!wI6eG$v@0sqt<#T%#CNK*UlhG zYk~2-===}uG(s3HMM;6JF+NHUi>7vv)_!H8MYB5`Sb~cR$PV^w2qk&qBm$jjIufka z4>pS*P-B%PUn|2kB*0k4UV7Wui02@SK7X><%g(gu4|?PxJKawnIfv9NpUftW!-*TG zq3t)^6L4(}mSORFzX}aM@s#MldrQ2EovZ3nR9iGW?L_|LmiMM_7~P9@A$`0T{}$`M zcJZfq5v>qv1_Z}4HHE&mY?y-@adJJQvY?d6=a1NFRCKu8Myt=9V~3jiZ=4=ZkVa~0 zn#R$}g5qK&tQuP^n8RVlHzk53NIEI9^Vj=l>Dp28FC4u8N3M{+OnRZdm|v|IdGR!? z^Y4qB@}MK&oVbiaVgrR-A@dF)$x_GeDe}y-cAAj7AK2+rtNj_!lfv_ev+0Wjl`^#( zO|+lU(=+iK^i`Sw)asYHIBe?^ zCJR9lAv8!;$7hsrd%0>5AeAQWw0_<+#KPD`Ih^Ge@6BwoZmny?wC zDoDlN$q2#t*?BXCVQEPIDa2aafyVE$R>EGpj$+L>HcZ}+*om@}SiX0U|pc3TXSesd~K3ea5hDlB{;CDW%yGl4a(nnV&3Mjc}1p z!&k%Xm^Ramp{U&Bd$@!AGo$LtrGYYV%l$d|Bfr{lqx_FXp%O(I+NG3_ZgcQbUoWPr}=Ow@p83c3$Xpwpt! zpHVxCqqs$r6=W@&6uK}}#U%-vb~=h;+9Kn$XUDFbZ|$UM^H3m6J7SNNvCvG5ti?Ce zw5(~i?=ZpB0wc{GAQwq5`H-Dqn0p_ZLNQ#JH8+kr(1+-v#W##yLFQ!5tx1WMK+|bJ z-@3{@M0?r_x%chfMDGOyc{4qr#KLe8a>Rd$-}e4I8mi(d|( zhxtbNI(hvayVwMM-mH8T>yhp5YZN^NABP=J3X3MKk+FRnduGGZrc7_`r|(CImE*}u zG!2f$G~S0!`evlVbg2lm-L5$NV>drl5A1Zuy$&ke53kR~Q}fQ-_3na(*cf%27I)Jt zk6s>nN%WHG<<+&g&-n+1y&UY99vyvOk<&GU!D?*#s9&ibeVZ!0 zi+qd)^>e)U>sxF5VySZ;x`GG-I3gUE{AeG2rZWrhf5I2i@=$iKYo^}%lK*o_Fw~*T z(EPmX)Yulg=5NcwEopt*sXkl@JLU_gurH#iw|JhUZ)>HfM*CVk@Yh4!YFAL5>3DghR;EYCohs0^160;IXuuHF6YGWLw1nt10vB&^*h1&1kBJJg!@297)RNPvM6d7mSCsOV49V5GM_{0mlSCh~1Ny&k7wa94{4R-Q zaF@RFRo65OTO{F>zVc#*_ByUmO46@BKg}guuKYK9T$Ud8 z1^Hu6@2bc@=;J>@DF{D`KXYuN9}tZ5oP&M+1V;P@ag5rGM`xPbgIE|uFBoax+{XP4 z_Ox;L(;zKA;HkQu*vPZYl`dY8&@q%k1e!PJc1CMz6&FSush#8wmZlSa5W?lYo~aBs zI#?ewYb23@lD31(=_)k%)z!&Mn}g_^JSZ8yW&`tU=qMG|v7fcL3>xNm z$KlJ+wj_5K9MkwJIrIH&TG4U`C(=a+Qkzr3zR>}^#`!9Zu9ET4?t$52SWrD2l)aXl ztCpr#ot5*8bB<8SId1}qM^Wy zbb_gnu%BUl8C6f;O_ce1nwg6|3x5y{|&m!p#uN_ delta 3631 zcmeHI|4*Am7{7bl(iYwq-hP2H5vXj)Fx%{=S=3EZ-Haw|S=}!t`h$>7&0<2txyTRN z_8n~?X41Vb&24_kU{hI)E)dzyU`E&vn`B7F2y-N8I?NIm7h8-87A!sQu3UKy>R-_J z>9zN{d++%?&*!=kYl|3p&PlcNbS&3==~4RuDGP2D+-#$K{j?@Fcj z8Yhy;x~GkpB(sf1Oy`dpF-ayipmV3>nupG^VIC;&5R%H{qLeuZJV0PQ{0zQuQvROC zJ1Es|Y)LQ+ToTg|>8BY zN_k#TMNeHcyZ5w$1;L;?0O;<{(TIu~v4c_=F(d4N#3I%^&|HnHcB?}L`o9Fu{W7;C zl(GgvWnOQHTCX_#SRa*#By_X4q-=fmon^al%6_{#K>qCn2m&(z_*NVqgV=OM4)T0_ z)->RTzL}G%T`J(hF}mN#8FKeJ*@;dDO^wKL6?)Ye3&5b9uKBSxEsshb6>t;e%l4e% znK=9i;y-5Oo*Ww*{6TiR)XjMokk+!CB`wJ-EG$i9eRQn_>v!b=sg`ljXO-oit&VCd zupX|*(R*^Hj1|h~SxHRHZcd-i5|+;@Q!M5A2NR;j4&%OzdO;p z?7$AJbRP?>hyAG6C7aE+svHnK)^BdcokY&&0^rJi1^_2isj|l6E~2@gVMsq7z@w^i z8M27?SF6D1_*(b|pv#l3Ce;G#;f7kT005{*u99U2S1yqb6X`(<*NU2%D=+GMODV?} zUCKC*CBW-f6iit|(8IRCdzA4j`4Kc!uS~E7evcRU=()>hHlEFr;c?J{X7<~kYgn3y zI*rO_h)!BaI8VO`>;o@@CiHBh=@1@hP;PKmzhL!*U?pSy5cX@2D?HhNHFu121P@T> zUeKp5ihQQYUnvqJ>jW-7(SFX~ukBD&URxhmQ_u6SIpe_;<+SFrfvmEh;^-bFvzC3w zlPd57zo6)hWoV^ zMPlg$R38&}Rs6Tn^KZyL=tWb9oLk^_b_eZ-IC@aYlx`=0n_wqRB<(CYj5J@j$n7 z10sFO;(~`!e6REqep6O!A=Zy6^QGP;@PRQo5}feR3p1}Dugz_&eXPV>Xg&_xyR-p? zwo=;4Xj5r((B{P2fXjIV9~iOCOSp5RyVQYOd0*Snp6{{1Eu z;@> IM_COL32_B_SHIFT) & 0xFF) * s, + ((in >> IM_COL32_G_SHIFT) & 0xFF) * s, + ((in >> IM_COL32_R_SHIFT) & 0xFF) * s, + ((in >> IM_COL32_A_SHIFT) & 0xFF) * s); +} + +ImU32 ImGuiToolkit::ColorConvertFloat4ToARGB(const ImVec4& in) +{ + ImU32 out; + out = ((ImU32)IM_F32_TO_INT8_SAT(in.x)) << IM_COL32_B_SHIFT; + out |= ((ImU32)IM_F32_TO_INT8_SAT(in.y)) << IM_COL32_G_SHIFT; + out |= ((ImU32)IM_F32_TO_INT8_SAT(in.z)) << IM_COL32_R_SHIFT; + out |= ((ImU32)IM_F32_TO_INT8_SAT(in.w)) << IM_COL32_A_SHIFT; + return out; +} diff --git a/src/ImGuiToolkit.h b/src/ImGuiToolkit.h index a0ff65a..5930e92 100644 --- a/src/ImGuiToolkit.h +++ b/src/ImGuiToolkit.h @@ -26,7 +26,7 @@ namespace ImGuiToolkit // buttons and gui items with icon bool ButtonIcon (int i, int j, const char* tooltip = nullptr, bool expanded = false); - bool ButtonIconToggle (int i, int j, int i_toggle, int j_toggle, bool* toggle, const char *tooltip = nullptr); + bool ButtonIconToggle (int i, int j, bool* toggle, const char *tooltip = nullptr); bool ButtonIconMultistate (std::vector > icons, int* state, std::vector tooltips); bool MenuItemIcon (int i, int j, const char* label, const char* shortcut = nullptr, bool selected = false, bool enabled = true); bool SelectableIcon(int i, int j, const char* label, bool selected, const ImVec2& size_arg = ImVec2(0,0)); @@ -106,6 +106,9 @@ namespace ImGuiToolkit data->DesiredSize.x = data->DesiredSize.y = (data->DesiredSize.x > data->DesiredSize.y ? data->DesiredSize.x : data->DesiredSize.y); } }; + + ImVec4 ColorConvertARGBToFloat4(ImU32 in); + ImU32 ColorConvertFloat4ToARGB(const ImVec4 &in); } #endif // __IMGUI_TOOLKIT_H_ diff --git a/src/ImGuiVisitor.cpp b/src/ImGuiVisitor.cpp index 10298a2..a232e3e 100644 --- a/src/ImGuiVisitor.cpp +++ b/src/ImGuiVisitor.cpp @@ -1858,9 +1858,9 @@ void ImGuiVisitor::visit(TextSource &s) // Prepare display text static int numlines = 0; const ImGuiContext &g = *GImGui; - ImVec2 fieldsize(w, MAX(3, numlines) * g.FontSize + g.Style.ItemSpacing.y + g.Style.FramePadding.y); + ImVec2 fieldsize(w, MAX(4, numlines) * g.FontSize + g.Style.ItemSpacing.y + g.Style.FramePadding.y); - // Editor + // Text contents std::string _contents = tc->text(); // if the content is a subtitle file if (tc->isSubtitle()) { @@ -1876,12 +1876,12 @@ void ImGuiVisitor::visit(TextSource &s) if (ImGuiToolkit::IconButton(3, 5, "Open")) SystemToolkit::open(_contents.c_str()); } - // general case of free text + // general case of free text : text editor else { if (ImGuiToolkit::InputTextMultiline("Text", &_contents, fieldsize, &numlines)) { info.reset(); tc->setText(_contents); - Action::manager().store(s.name() + ": Change text"); + Action::manager().store(s.name() + " Change text"); } botom = ImGui::GetCursorPos(); @@ -1890,37 +1890,173 @@ void ImGuiVisitor::visit(TextSource &s) if (ImGuiToolkit::IconButton(ICON_FA_COPY, "Copy")) ImGui::SetClipboardText(_contents.c_str()); ImGui::SetCursorPos( - ImVec2(top.x + 0.9 * ImGui::GetFrameHeight(), botom.y - ImGui::GetFrameHeight())); + ImVec2(top.x + 0.95 * ImGui::GetFrameHeight(), botom.y - ImGui::GetFrameHeight())); if (ImGuiToolkit::IconButton(ICON_FA_PASTE, "Paste")) { _contents = std::string(ImGui::GetClipboardText()); info.reset(); tc->setText(_contents); - Action::manager().store(s.name() + ": Change text"); + Action::manager().store(s.name() + " Change text"); } + ImGui::SetCursorPos(ImVec2(top.x, botom.y - 2.f * ImGui::GetFrameHeight())); + if (ImGuiToolkit::IconButton(ICON_FA_CODE, "Pango syntax")) + SystemToolkit::open("https://docs.gtk.org/Pango/pango_markup.html"); } - // Properties + + // Text Properties ImGui::SetCursorPos(botom); + ImVec4 color = ImGuiToolkit::ColorConvertARGBToFloat4(tc->color()); + if (ImGui::ColorEdit4("Text Color", (float *) &color, ImGuiColorEditFlags_AlphaPreview | + ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel) ) { + tc->setColor( ImGuiToolkit::ColorConvertFloat4ToARGB(color) ); + } + if (ImGui::IsItemDeactivatedAfterEdit()) + Action::manager().store( s.name() + " Change font color" ); std::string font = tc->fontDescriptor(); + ImGui::SameLine(0, IMGUI_SAME_LINE); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - ImGuiToolkit::InputText("Font", &font); + ImGuiToolkit::InputText("##Font", &font, ImGuiInputTextFlags_EnterReturnsTrue); if (ImGui::IsItemDeactivatedAfterEdit()) { tc->setFontDescriptor(font); Action::manager().store( s.name() + " Change font"); } + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::TextButton("Font")) { + tc->setFontDescriptor("arial 24"); + tc->setColor(0xffffffff); + Action::manager().store(s.name() + " Reset font"); + } + botom = ImGui::GetCursorPos(); + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::IconButton(1, 13, "Pango font description")) + SystemToolkit::open("https://docs.gtk.org/Pango/type_func.FontDescription.from_string.html"); + ImGui::SetCursorPos(botom); - int align = tc->halignment(); + color = ImGuiToolkit::ColorConvertARGBToFloat4(tc->outlineColor()); + if (ImGui::ColorEdit4("Text Outline Color", (float *) &color, ImGuiColorEditFlags_AlphaPreview | + ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel) ) { + tc->setOutlineColor( ImGuiToolkit::ColorConvertFloat4ToARGB(color) ); + } + if (ImGui::IsItemDeactivatedAfterEdit()) + Action::manager().store( s.name() + " Change outline color" ); + ImGui::SameLine(0, IMGUI_SAME_LINE); + int outline = tc->outline(); ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - if (ImGui::Combo("Horizontal", &align, "Left\0Center\0Right\0Absolute\0")) { - tc->setHalignment(align); - Action::manager().store( s.name() + " Horizontal align"); + if (ImGui::Combo("##Outline", &outline, "None\0Border\0Border & shadow\0")) { + tc->setOutline(outline); + Action::manager().store(s.name() + " Change outline"); + } + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::TextButton("Outline")) { + tc->setOutline(2); + tc->setOutlineColor(0xFF000000); + Action::manager().store(s.name() + " Reset outline"); } - align = tc->valignment(); - ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); - if (ImGui::Combo("Vertical", &align, "Baseline\0Bottom\0top\0Absolute\0Center\0")) { - tc->setValignment(align); - Action::manager().store( s.name() + " Vertical align"); + // HORIZONTAL alignment + bool on = true; + uint var = tc->horizontalAlignment(); + on = var == 0; + float _x = ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; + _x -= 4.f * (g.FontSize + g.Style.FramePadding.x + IMGUI_SAME_LINE); + if (var != 1) { + // not centered + ImGui::SetNextItemWidth(_x); + if (var > 2) { + // Absolute position + float align_x = tc->horizontalPadding(); + if (ImGui::SliderFloat("##Posx", &align_x, 0.f, 1.f, "%.2f")) { + tc->setHorizontalPadding(align_x); + } + if (ImGui::IsItemHovered()) + ImGuiToolkit::ToolTip( "Coordinates" ); + } else { + // padding top or bottom + int pad_x = (int) tc->horizontalPadding(); + if (ImGui::SliderInt("##Padx", &pad_x, 0, 1000)) { + tc->setHorizontalPadding((float) pad_x); + } + if (ImGui::IsItemHovered()) + ImGuiToolkit::ToolTip( "Padding" ); + } + ImGui::SameLine(0, IMGUI_SAME_LINE); + } else { + _x += IMGUI_SAME_LINE + g.Style.FramePadding.x; + ImGui::SetCursorPosX(_x); + } + if (ImGuiToolkit::ButtonIconToggle(17, 16, &on, "Left")) + tc->setHorizontalAlignment(0); + ImGui::SameLine(0, IMGUI_SAME_LINE); + on = var == 1; + if (ImGuiToolkit::ButtonIconToggle(18, 16, &on, "Center")) + tc->setHorizontalAlignment(1); + ImGui::SameLine(0, IMGUI_SAME_LINE); + on = var == 2; + if (ImGuiToolkit::ButtonIconToggle(19, 16, &on, "Right")) + tc->setHorizontalAlignment(2); + ImGui::SameLine(0, IMGUI_SAME_LINE); + on = var == 3; + if (ImGuiToolkit::ButtonIconToggle(6, 10, &on, "Absolute")) + tc->setHorizontalAlignment(3); + if (var != tc->horizontalAlignment()) + Action::manager().store(s.name() + " Change h-align"); + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::TextButton("Horizontal")) { + tc->setHorizontalAlignment(1); + Action::manager().store(s.name() + " Reset h-align"); + } + + // VERTICAL alignment + var = tc->verticalAlignment(); + on = var == 0; + _x = ImGui::GetContentRegionAvail().x IMGUI_RIGHT_ALIGN; + _x -= 4.f * (g.FontSize + g.Style.FramePadding.x + IMGUI_SAME_LINE); + if (var != 2) { + // not centered + ImGui::SetNextItemWidth(_x); + if (var > 2) { + // Absolute position + float align_y = tc->verticalPadding(); + if (ImGui::SliderFloat("##Posy", &align_y, 0.f, 1.f, "%.2f")) { + tc->setVerticalPadding(align_y); + } + if (ImGui::IsItemHovered()) + ImGuiToolkit::ToolTip( "Coordinates" ); + } else { + // padding top or bottom + int pad_y = (int) tc->verticalPadding(); + if (ImGui::SliderInt("##Pady", &pad_y, 0, 1000)) { + tc->setVerticalPadding((float) pad_y); + } + if (ImGui::IsItemHovered()) + ImGuiToolkit::ToolTip( "Padding" ); + } + ImGui::SameLine(0, IMGUI_SAME_LINE); + } else { + // no value slider for centered + _x += IMGUI_SAME_LINE + g.Style.FramePadding.x; + ImGui::SetCursorPosX(_x); + } + if (ImGuiToolkit::ButtonIconToggle(1, 17, &on, "Bottom")) + tc->setVerticalAlignment(0); + ImGui::SameLine(0, IMGUI_SAME_LINE); + on = var == 2; + if (ImGuiToolkit::ButtonIconToggle(3, 17, &on, "Center")) + tc->setVerticalAlignment(2); + ImGui::SameLine(0, IMGUI_SAME_LINE); + on = var == 1; + if (ImGuiToolkit::ButtonIconToggle(2, 17, &on, "Top")) + tc->setVerticalAlignment(1); + ImGui::SameLine(0, IMGUI_SAME_LINE); + on = var == 3; + if (ImGuiToolkit::ButtonIconToggle(3, 10, &on, "Absolute")) + tc->setVerticalAlignment(3); + if (var != tc->verticalAlignment()) + Action::manager().store(s.name() + " Change v-align"); + ImGui::SameLine(0, IMGUI_SAME_LINE); + if (ImGuiToolkit::TextButton("Vertical")) { + tc->setVerticalAlignment(2); + Action::manager().store(s.name() + " Reset v-align"); } botom = ImGui::GetCursorPos(); diff --git a/src/Log.cpp b/src/Log.cpp index 9f2e8ea..d562e6b 100644 --- a/src/Log.cpp +++ b/src/Log.cpp @@ -100,7 +100,7 @@ struct AppLog // window ImGui::SameLine(0, 0); static bool numbering = true; - ImGuiToolkit::ButtonIconToggle(4, 12, 4, 12, &numbering ); + ImGuiToolkit::ButtonIconToggle(4, 12, &numbering ); ImGui::SameLine(); bool clear = ImGui::Button( ICON_FA_BACKSPACE " Clear"); ImGui::SameLine(); diff --git a/src/SessionCreator.cpp b/src/SessionCreator.cpp index c0c508f..3d5fa21 100644 --- a/src/SessionCreator.cpp +++ b/src/SessionCreator.cpp @@ -1271,14 +1271,34 @@ void SessionLoader::visit(TextSource &s) s.contents()->setFontDescriptor(font); } } - uint alignment = s.contents()->halignment(); - _contents->QueryUnsignedAttribute("halignment", &alignment); - if (s.contents()->halignment() != alignment) - s.contents()->setHalignment(alignment); - alignment = s.contents()->valignment(); - _contents->QueryUnsignedAttribute("valignment", &alignment); - if (s.contents()->valignment() != alignment) - s.contents()->setValignment(alignment); + uint var = s.contents()->horizontalAlignment(); + _contents->QueryUnsignedAttribute("halignment", &var); + if (s.contents()->horizontalAlignment() != var) + s.contents()->setHorizontalAlignment(var); + var = s.contents()->verticalAlignment(); + _contents->QueryUnsignedAttribute("valignment", &var); + if (s.contents()->verticalAlignment() != var) + s.contents()->setVerticalAlignment(var); + var = s.contents()->color(); + _contents->QueryUnsignedAttribute("color", &var); + if (s.contents()->color() != var) + s.contents()->setColor(var); + var = s.contents()->outline(); + _contents->QueryUnsignedAttribute("outline", &var); + if (s.contents()->outline() != var) + s.contents()->setOutline(var); + var = s.contents()->outlineColor(); + _contents->QueryUnsignedAttribute("outline-color", &var); + if (s.contents()->outlineColor() != var) + s.contents()->setOutlineColor(var); + float x = 0.f; + _contents->QueryFloatAttribute("x", &x); + if (s.contents()->horizontalPadding() != x) + s.contents()->setHorizontalPadding(x); + float y = 0.f; + _contents->QueryFloatAttribute("y", &y); + if (s.contents()->verticalPadding() != y) + s.contents()->setVerticalPadding(y); } XMLElement* res = xmlCurrent_->FirstChildElement("resolution"); diff --git a/src/SessionVisitor.cpp b/src/SessionVisitor.cpp index ac0492d..0a66567 100644 --- a/src/SessionVisitor.cpp +++ b/src/SessionVisitor.cpp @@ -866,8 +866,13 @@ void SessionVisitor::visit (TextSource& s) } contents->SetAttribute("font-desc", s.contents()->fontDescriptor().c_str() ); - contents->SetAttribute("halignment", s.contents()->halignment() ); - contents->SetAttribute("valignment", s.contents()->valignment() ); + contents->SetAttribute("color", s.contents()->color() ); + contents->SetAttribute("halignment", s.contents()->horizontalAlignment() ); + contents->SetAttribute("valignment", s.contents()->verticalAlignment() ); + contents->SetAttribute("outline", s.contents()->outline() ); + contents->SetAttribute("outline-color", s.contents()->outlineColor() ); + contents->SetAttribute("x", s.contents()->horizontalPadding() ); + contents->SetAttribute("y", s.contents()->verticalPadding() ); xmlCurrent_->InsertEndChild(contents); } diff --git a/src/TextSource.cpp b/src/TextSource.cpp index 1d9e17d..f71c124 100644 --- a/src/TextSource.cpp +++ b/src/TextSource.cpp @@ -77,9 +77,9 @@ bool TextContents::SubtitleDiscoverer(const std::string &path) TextContents::TextContents() : Stream(), src_(nullptr), txt_(nullptr), - halignment_(1), valignment_(4) + fontdesc_("arial 24"), color_(0xffffffff), outline_(2), outline_color_(4278190080), + halignment_(1), valignment_(2), xalignment_(0.f), yalignment_(0.f) { - fontdesc_ = "arial, 24"; } void TextContents::execute_open() @@ -155,9 +155,30 @@ void TextContents::execute_open() g_object_set(G_OBJECT(txt_), "text", text_.c_str(), NULL); } - g_object_set(G_OBJECT(txt_), "font-desc", fontdesc_.c_str(), NULL); - g_object_set(G_OBJECT(txt_), "halignment", halignment_, NULL); - g_object_set(G_OBJECT(txt_), "valignment", valignment_, NULL); + g_object_set(G_OBJECT(txt_), + "font-desc", + fontdesc_.c_str(), + "color", + color_, + "outline-color", + outline_color_, + "halignment", + halignment_ < 3 ? halignment_ : 5, + "line-alignment", + halignment_ < 3 ? halignment_ : 1, + "valignment", + valignment_ < 2 ? valignment_ + 1 + : valignment_ > 2 ? 5 + : 4, + "draw-outline", + outline_ > 0, + "draw-shadow", + outline_ > 1, + "auto-resize", + FALSE, + NULL); + setHorizontalPadding(xalignment_); + setVerticalPadding(yalignment_); } @@ -225,7 +246,7 @@ void TextContents::setText(const std::string &t) text_ = t; // apply if ready if (txt_) - g_object_set(G_OBJECT(txt_),"text", text_.c_str(), NULL); + g_object_set(G_OBJECT(txt_), "text", text_.c_str(), NULL); } } @@ -240,25 +261,96 @@ void TextContents::setFontDescriptor(const std::string &fd) } } -void TextContents::setHalignment(uint h) +void TextContents::setColor(uint c) +{ + if ( color_ != c ) { + // set value + color_ = c; + // apply if ready + if (txt_) + g_object_set(G_OBJECT(txt_), "color", color_, NULL); + } +} + + +void TextContents::setOutline(uint o) +{ + if (outline_ != o) { + // set value + outline_ = o; + // apply if ready + if (txt_) { + g_object_set(G_OBJECT(txt_), + "draw-outline", + outline_ > 0, + "draw-shadow", + outline_ > 1, + NULL); + } + } +} + +void TextContents::setOutlineColor(uint c) +{ + if ( outline_color_ != c ) { + // set value + outline_color_ = c; + // apply if ready + if (txt_) + g_object_set(G_OBJECT(txt_), "outline-color", outline_color_, NULL); + } +} + +void TextContents::setHorizontalAlignment(uint h) { if ( halignment_ != h ) { // set value halignment_ = h; // apply if ready - if (txt_) - g_object_set(G_OBJECT(txt_),"halignment", halignment_, NULL); + if (txt_) { + g_object_set(G_OBJECT(txt_), + "halignment", halignment_ < 3 ? halignment_ : 4, + "line-alignment", halignment_ < 3 ? halignment_ : 1, + NULL); + } } } -void TextContents::setValignment(uint v) +void TextContents::setVerticalAlignment(uint v) { if ( valignment_ != v ) { // set value valignment_ = v; // apply if ready - if (txt_) - g_object_set(G_OBJECT(txt_),"valignment", valignment_, NULL); + if (txt_) { + g_object_set(G_OBJECT(txt_), + "valignment", valignment_ < 2 ? valignment_+1 : valignment_ > 2 ? 3 : 4, + NULL); + } + } +} + +void TextContents::setHorizontalPadding(float x) +{ + xalignment_ = x; + // apply if ready + if (txt_) { + if (halignment_ > 2) + g_object_set(G_OBJECT(txt_), "xpos", CLAMP(xalignment_, 0.f, 1.f), NULL); + else + g_object_set(G_OBJECT(txt_), "xpad", CLAMP((int)xalignment_, 0, 10000), NULL); + } +} + +void TextContents::setVerticalPadding(float y) +{ + yalignment_ = y; + // apply if ready + if (txt_) { + if (valignment_ > 2) + g_object_set(G_OBJECT(txt_), "ypos", CLAMP(yalignment_, 0.f, 1.f), NULL); + else + g_object_set(G_OBJECT(txt_), "ypad", CLAMP((int)yalignment_, 0, 10000), NULL); } } diff --git a/src/TextSource.h b/src/TextSource.h index bdf5166..db15885 100644 --- a/src/TextSource.h +++ b/src/TextSource.h @@ -18,23 +18,44 @@ public: void setFontDescriptor(const std::string &fd); inline std::string fontDescriptor() const { return fontdesc_; } - /* (0): left - left - * (1): center - center - * (2): right - right - * (4): Absolute position clamped to canvas - position - * (5): Absolute position - absolute + + /* + * ARGB integer color * */ - void setHalignment(uint h); - inline uint halignment() const { return halignment_; } - /* (0): baseline - baseline - * (1): bottom - bottom - * (2): top - top - * (3): Absolute position clamped to canvas - position - * (4): center - center - * (5): Absolute position - absolute + void setColor(uint c); + inline uint color() const { return color_; } + + /* (0): None + * (1): outline + * (2): outline and shadow * */ - void setValignment(uint v); - inline uint valignment() const { return valignment_; } + void setOutline(uint v); + inline uint outline() const { return outline_; } + void setOutlineColor(uint c); + inline uint outlineColor() const { return outline_color_; } + + /* (0): left + * (1): center + * (2): right + * (3): Absolute position + * */ + void setHorizontalAlignment(uint h); + inline uint horizontalAlignment() const { return halignment_; } + + void setHorizontalPadding(float x); + inline float horizontalPadding() const { return xalignment_; } + + /* (0): bottom + * (1): top + * (2): center + * (3): Absolute position + * */ + void setVerticalAlignment(uint v); + inline uint verticalAlignment() const { return valignment_; } + + void setVerticalPadding(float y); + inline float verticalPadding() const { return yalignment_; } + private: GstElement *src_; @@ -44,8 +65,13 @@ private: std::string text_; std::string fontdesc_; + uint color_; + uint outline_; + uint outline_color_; uint halignment_; uint valignment_; + float xalignment_; + float yalignment_; }; diff --git a/src/UserInterfaceManager.cpp b/src/UserInterfaceManager.cpp index a658652..f9f21c6 100644 --- a/src/UserInterfaceManager.cpp +++ b/src/UserInterfaceManager.cpp @@ -3832,13 +3832,13 @@ void Navigator::RenderNewPannel(const ImVec2 &iconsize) else if (generated_type == 1) { static std::vector > _examples = {{"Hello", "Hello world!"}, - {"Italics", "Text in italics"}, - {"Multiline", "One\nTwo\nThree\nFour\nFive"}, - {"Code", "Monospace"}}; + {"Rich text", "Text in italics or bold"}, + {"Multiline", "One\nTwo\nThree\nFour\nFive"} }; static std::string _contents = _examples[0].second; // Editor - if (SystemToolkit::file_exists(_contents)) { + if ( (SystemToolkit::has_extension(_contents, "srt") || SystemToolkit::has_extension(_contents, "sub") ) + && SystemToolkit::file_exists(_contents)) { static char dummy_str[1024]; ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN); snprintf(dummy_str, 1024, "%s", _contents.c_str()); @@ -3873,10 +3873,6 @@ void Navigator::RenderNewPannel(const ImVec2 &iconsize) ImGui::TextDisabled("Explore online"); if (ImGui::Selectable(ICON_FA_EXTERNAL_LINK_ALT " Pango syntax")) SystemToolkit::open("https://docs.gtk.org/Pango/pango_markup.html"); - if (ImGui::Selectable(ICON_FA_EXTERNAL_LINK_ALT " Gstreamer")) - SystemToolkit::open( - "https://gstreamer.freedesktop.org/documentation/pango/" - "textoverlay.html?gi-language=c#textoverlay-page"); if (ImGui::Selectable(ICON_FA_EXTERNAL_LINK_ALT " SubRip files")) SystemToolkit::open("https://en.wikipedia.org/wiki/SubRip"); ImGui::EndCombo();