From e47e49fb750cc0e29a5e8a60b29e7bcaa4127173 Mon Sep 17 00:00:00 2001 From: Adeel Kazmi Date: Fri, 23 Dec 2016 10:41:29 +0000 Subject: [PATCH] Added a tooltip example Change-Id: I5909a67d2bff74f23c758862198df4da1e6c4627 --- build/tizen/CMakeLists.txt | 1 + com.samsung.dali-demo.xml | 3 + demo/dali-demo.cpp | 1 + examples/tooltip/tooltip-example.cpp | 180 +++++++++++++++++++++ resources/images/tooltip-tail-above.png | Bin 0 -> 3186 bytes resources/images/tooltip-tail-below.png | Bin 0 -> 3242 bytes resources/images/tooltip.9.png | Bin 0 -> 3016 bytes resources/po/as.po | 3 + resources/po/de.po | 3 + resources/po/en_GB.po | 3 + resources/po/en_US.po | 3 + resources/po/es.po | 3 + resources/po/fi.po | 3 + resources/po/ko.po | 3 + resources/po/ml.po | 3 + resources/po/ur.po | 3 + resources/po/zn_CH.po | 3 + resources/style/.gitignore | 1 + .../style/mobile/tooltip-example-theme.json.in | 85 ++++++++++ resources/style/tooltip-example-theme.json.in | 85 ++++++++++ shared/dali-demo-strings.h | 10 +- 21 files changed, 392 insertions(+), 4 deletions(-) create mode 100644 examples/tooltip/tooltip-example.cpp create mode 100644 resources/images/tooltip-tail-above.png create mode 100644 resources/images/tooltip-tail-below.png create mode 100644 resources/images/tooltip.9.png create mode 100644 resources/style/mobile/tooltip-example-theme.json.in create mode 100644 resources/style/tooltip-example-theme.json.in diff --git a/build/tizen/CMakeLists.txt b/build/tizen/CMakeLists.txt index 168d55e..309f3e0 100644 --- a/build/tizen/CMakeLists.txt +++ b/build/tizen/CMakeLists.txt @@ -105,6 +105,7 @@ CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/contact-cards-example-theme.json.in ${LOCAL_S CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/style-example-theme-one.json.in ${LOCAL_STYLE_DIR}/style-example-theme-one.json ) CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/style-example-theme-two.json.in ${LOCAL_STYLE_DIR}/style-example-theme-two.json ) CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/style-example-theme-three.json.in ${LOCAL_STYLE_DIR}/style-example-theme-three.json ) +CONFIGURE_FILE( ${LOCAL_STYLE_DIR}/tooltip-example-theme.json.in ${LOCAL_STYLE_DIR}/tooltip-example-theme.json ) MESSAGE("Configured ${LOCAL_STYLE_DIR}/style-example-theme<>.json files") FILE(GLOB LOCAL_STYLES_LIST "${LOCAL_STYLE_DIR}/*.json") diff --git a/com.samsung.dali-demo.xml b/com.samsung.dali-demo.xml index 7fe738b..046061d 100644 --- a/com.samsung.dali-demo.xml +++ b/com.samsung.dali-demo.xml @@ -181,4 +181,7 @@ + + + diff --git a/demo/dali-demo.cpp b/demo/dali-demo.cpp index bbf9b02..904e3be 100644 --- a/demo/dali-demo.cpp +++ b/demo/dali-demo.cpp @@ -88,6 +88,7 @@ int DALI_EXPORT_API main(int argc, char **argv) demo.AddExample(Example("contact-cards.example", DALI_DEMO_STR_TITLE_CONTACT_CARDS)); demo.AddExample(Example("flex-container.example", DALI_DEMO_STR_TITLE_FLEXBOX_PLAYGROUND)); demo.AddExample(Example("fpp-game.example", DALI_DEMO_STR_TITLE_FPP_GAME)); + demo.AddExample(Example("tooltip.example", DALI_DEMO_STR_TITLE_TOOLTIP)); demo.SortAlphabetically( true ); diff --git a/examples/tooltip/tooltip-example.cpp b/examples/tooltip/tooltip-example.cpp new file mode 100644 index 0000000..3af4e11 --- /dev/null +++ b/examples/tooltip/tooltip-example.cpp @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include + +using namespace Dali; +using namespace Dali::Toolkit; + +namespace +{ +const Vector4 STAGE_COLOR( 211.0f / 255.0f, 211.0f / 255.0f, 211.0f / 255.0f, 1.0f ); ///< The color of the stage +const char * const THEME_PATH( DEMO_STYLE_DIR "tooltip-example-theme.json" ); ///< The theme used for this example +const float POSITION_INCREMENTER( 0.2f ); ///< The position difference between the controls along the Y-Axis. +} // unnamed namespace + +/** + * @brief Creates a controller which demonstrates the tooltip functionality in control. + * + * The Control base class supports tooltip functionality. However, the Toolkit Tooltip style is only set on Buttons by default. + * This example portrays the different ways in which a tooltip can be displayed and customised. + */ +class TooltipController : public ConnectionTracker +{ +public: + + TooltipController( Application& application ) + : mApplication( application ), + previousPosition( 0.0f ) + { + // Connect to the Application's Init signal + mApplication.InitSignal().Connect( this, &TooltipController::Create ); + } + +private: + + // The Init signal is received once (only) during the Application lifetime + void Create( Application& application ) + { + // Hide the indicator bar + application.GetWindow().ShowIndicator( Dali::Window::INVISIBLE ); + + // Set the stage background color and connect to the stage's key signal to allow Back and Escape to exit. + Stage stage = Stage::GetCurrent(); + stage.SetBackgroundColor( STAGE_COLOR ); + stage.KeyEventSignal().Connect( this, &TooltipController::OnKeyEvent ); + const Vector2 stageSize = stage.GetSize(); + + // Add a text label at the top for information purposes + Control label = TextLabel::New( "Hover over buttons to see tooltip" ); + label.SetParentOrigin( ParentOrigin::TOP_CENTER ); + label.SetAnchorPoint( AnchorPoint::TOP_CENTER ); + label.SetProperty( TextLabel::Property::HORIZONTAL_ALIGNMENT, "Center" ); + stage.Add( label ); + + // Simple tooltip from stylesheet + Control simple = PushButton::New(); + simple.SetStyleName( "TooltipTextOnly" ); + SetLabel( simple, "Simple" ); + Layout( simple, stageSize ); + stage.Add( simple ); + + // Tooltip with icon and text, from stylesheet + Control iconWithText = PushButton::New(); + iconWithText.SetStyleName( "TooltipArray" ); + SetLabel( iconWithText, "Icon with Text" ); + Layout( iconWithText, stageSize ); + stage.Add( iconWithText ); + + // Tooltip with custom style, from stylesheet + Control customFromStylesheet = PushButton::New(); + customFromStylesheet.SetStyleName( "TooltipCustom" ); + SetLabel( customFromStylesheet, "Custom From Stylesheet" ); + Layout( customFromStylesheet, stageSize ); + stage.Add( customFromStylesheet ); + + // Tooltip with custom style, from code + Control customFromCode = PushButton::New(); + SetLabel( customFromCode, "Custom From Code" ); + Layout( customFromCode, stageSize ); + customFromCode.SetProperty( DevelControl::Property::TOOLTIP, + Property::Map().Add( Tooltip::Property::CONTENT, + Property::Array().Add( Property::Map().Add( Visual::Property::TYPE, Visual::IMAGE ) + .Add( ImageVisual::Property::URL, DEMO_IMAGE_DIR "Logo-for-demo.png" ) ) + .Add( Property::Map().Add( Visual::Property::TYPE, DevelVisual::TEXT ) + .Add( TextVisual::Property::TEXT_COLOR, Color::WHITE ) + .Add( TextVisual::Property::TEXT, "Custom coded style\nat hover point" ) + .Add( TextVisual::Property::MULTI_LINE, true ) + .Add( TextVisual::Property::HORIZONTAL_ALIGNMENT, "CENTER" ) + .Add( TextVisual::Property::POINT_SIZE, 16 ) ) ) + .Add( Tooltip::Property::LAYOUT, Vector2( 2, 1 ) ) + .Add( Tooltip::Property::POSITION, Tooltip::Position::HOVER_POINT ) + .Add( Tooltip::Property::BACKGROUND, + Property::Map().Add( Tooltip::Background::Property::VISUAL, DEMO_IMAGE_DIR "tooltip.9.png" ) + .Add( Tooltip::Background::Property::BORDER, Rect< int >( 1, 5, 5, 1 ) ) ) + ); + stage.Add( customFromCode ); + } + + /** + * @brief Called when any key event is received + * + * Will use this to quit the application if Back or the Escape key is received + * @param[in] event The key event information + */ + void OnKeyEvent( const KeyEvent& event ) + { + if( event.state == KeyEvent::Down ) + { + if ( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) ) + { + mApplication.Quit(); + } + } + } + + /** + * @brief Sets the label on the control. + * @param[in] label The label to set. + */ + void SetLabel( Control control, std::string label ) + { + if( control ) + { + control.SetProperty( Button::Property::LABEL, + Property::Map().Add( Visual::Property::TYPE, DevelVisual::TEXT ) + .Add( TextVisual::Property::TEXT, label ) ); + } + } + + /** + * @brief Lays out the control in the appropriate location. + * @param[in] control The control to layout. + * @param[in] stageSize The size of the stage, passing it in so we don't have to retrieve it every time. + */ + void Layout( Control control, const Vector2& stageSize ) + { + if( control ) + { + previousPosition += POSITION_INCREMENTER; + control.SetResizePolicy( ResizePolicy::SIZE_RELATIVE_TO_PARENT, Dimension::ALL_DIMENSIONS ); + control.SetSizeModeFactor( Vector3( 0.75, 0.1, 1.0 ) ); + control.SetAnchorPoint( AnchorPoint::CENTER ); + control.SetParentOrigin( ParentOrigin::TOP_CENTER ); + control.SetY( stageSize.height * previousPosition ); + } + } + +private: + Application& mApplication; + float previousPosition; +}; + +int DALI_EXPORT_API main( int argc, char **argv ) +{ + Application application = Application::New( &argc, &argv, THEME_PATH ); + + TooltipController test( application ); + + application.MainLoop(); + + return 0; +} diff --git a/resources/images/tooltip-tail-above.png b/resources/images/tooltip-tail-above.png new file mode 100644 index 0000000000000000000000000000000000000000..9cbcfa09aabc24980f968f38d9b60a0f8d232e3b GIT binary patch literal 3186 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 Y2XQ$>t89>$8~^|S07*qoM6N<$g3@a4r2qf` literal 0 HcmV?d00001 diff --git a/resources/images/tooltip-tail-below.png b/resources/images/tooltip-tail-below.png new file mode 100644 index 0000000000000000000000000000000000000000..f24c92ee841b76623e62e23ede81624d282c63ce GIT binary patch literal 3242 zcmV;b3{~@qP)Oz@Z0f2-7z;ux~O9+4z06=<WDR*FRcSTFz- zW=q650N5=6FiBTtNC2?60Km==3$g$R3;-}uh=nNt1bYBr$Ri_o0EC$U6h`t_Jn<{8 z5a%iY0C<_QJh>z}MS)ugEpZ1|S1ukX&Pf+56gFW3VVXcL!g-k)GJ!M?;PcD?0HBc- z5#WRK{dmp}uFlRjj{U%*%WZ25jX z{P*?XzTzZ-GF^d31o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcq zjPo+3B8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S z1Au6Q;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO002awfhw>;8}z{#EWidF!3EsG z3;bXU&9EIRU@z1_9W=mEXoiz;4lcq~xDGvV5BgyU zp1~-*fe8db$Osc*A=-!mVv1NJjtCc-h4>-CNCXm#Bp}I%6j35eku^v$Qi@a{RY)E3 zJ#qp$hg?Rwkvqr$GJ^buyhkyVfwECO)C{#lxu`c9ghrwZ&}4KmnvWKso6vH!8a<3Q zq36)6Xb;+tK10Vaz~~qUGsJ8#F2=(`u{bOVlVi)VBCHIn#u~6ztOL7=^<&SmcLWlF zMZgI*1b0FpVIDz9SWH+>*hr`#93(Um+6gxa1B6k+CnA%mOSC4s5&6UzVlpv@SV$}* z))J2sFA#f(L&P^E5{W}HC%KRUNwK6<(h|}}(r!{C=`5+6G)NjFlgZj-YqAG9lq?`C z$c5yc>d>VnA`E_*3F2Qp##d8RZb=H01_mm@+|Cqnc9PsG(F5HIG_C zt)aG3uTh7n6Et<2In9F>NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWwr)$3XQ?}=hpK0&Z&W{| zep&sA23f;Q!%st`QJ}G3cbou<7-yIK2z4nfCCCtN2-XOGSWo##{8Q{ATurxr~;I`ytDs%xbip}RzP zziy}Qn4Z2~fSycmr`~zJ=lUFdFa1>gZThG6M+{g7vkW8#+YHVaJjFF}Z#*3@$J_By zLtVo_L#1JrVVB{Ak-5=4qt!-@Mh}c>#$4kh<88)m#-k<%CLtzEP3leVno>={htGUuD;o7bD)w_sX$S}eAxwzy?UvgBH(S?;#HZiQMoS*2K2 zT3xe7t(~nU*1N5{rxB;QPLocnp4Ml>u<^FZwyC!nu;thW+pe~4wtZn|Vi#w(#jeBd zlf9FDx_yoPJqHbk*$%56S{;6Kv~mM9!g3B(KJ}#RZ#@)!hR|78Dq|Iq-afF%KE1Brn_fm;Im z_u$xr8UFki1L{Ox>G0o)(&RAZ;=|I=wN2l97;cLaHH6leTB-XXa*h%dBOEvi`+x zi?=Txl?TadvyiL>SuF~-LZ;|cS}4~l2eM~nS7yJ>iOM;atDY;(?aZ^v+mJV$@1Ote z62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~pu715HdQEGA zUct(O!LkCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$+<4_1hi}Ti zncS4LsjI}fWY1>OX6feMEuLErma3QLmkw?X+1j)X-&VBk_4Y;EFPF_I+q;9dL%E~B zJh;4Nr^(LEJ3myURP{Rblsw%57T)g973R8o)DE9*xN#~;4_o$q%o z4K@u`jhx2fBXC4{U8Qn{*%*B$Ge=nny$HAYq{=vy|sI0 z_vss+H_qMky?OB#|JK!>IX&II^LlUh#rO5!7TtbwC;iULyV-Xq?ybB}ykGP{?LpZ? z-G|jbTmIbG@7#ZCz;~eY(cDM(28Dyq{*m>M4?_iynUBkc4TkHUI6gT!;y-fz>HMcd z&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M!p0uH$#^p{Ui4P` z?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&GcDTy000JJOGiWi{{a60 z|De66lK=n!32;bRa{vGf6951U69E94oEQKA00(qQO+^Rb3>*w57fiTIg8%>l+(|@1 zR9M5s*H4cOK^VvJ&&+Pv8_ryL8HkJ5#d-&9BodNABpeV#{E0Y7#Dihdvb#z`E)LP`l7?-AfSj^F_1a)5a} z?qTvZoWMaWKn^g#u^s?MIE?)mZUdxj)Q5#t9F6pQMWvLsNbm=X{$E|gC;Y@lv0+O^ zHcEIN7P_t*;dHf{rig%^0#;pE?Nxh(xo1I4}2m4y+$ zmZhHn2n)*{S@?{rRq6j_pv%2*5#N#FcUh+ifP#ewGfe&wH>Ra8Gav?>n!&<_xcy4k zz7ilTyu$q!lYhXiLi*GgU`7k)C;SKIobX&pG09bFbafdbgO|x(|l4o&} z>J%U>tdv+-j{g#k(>F0tWnrmp`bGc+3%3g&Kf}w|`QtW6_po9AO`M7MR9O38ZPGUe z2n%m<6A!~ktF_N-zQvf_!oK*$%W9kvr8Q_dZVr3mdfZljN~twKarshP{V64b{P}FR cYG{}1FK--BVhA0^g@7yNGJ3rNRckR22hX=q7o8H zAjA+7RK$+Bf@?uV1eFz81yOKSimU~(U||vLeS<72%DPyvp>jX4guQd;ez-IDKXc~% z=9%|>-se5%%L72`%-I>Frlz>>y9`2%1I01}PIlV$)=hXH_-&(Dwn&}aZ)Cl(0B z0JK>E;Kk462>@t?05Cl#XORGaRtEqUssHfF_&3i~r6-S zdvZkb$uo=qfR-r@i2?u>0HiK^QJ9j&sdFMGSttOQ?HH^{F5eGzzYbQWO;V1 z?&6(u9?C7wm zHU3InDvwfTPL~EL@0gP}m5tAvI!l%r6Ec+{L77L877(b^#j(ou5}BXUQzD9-$}b95 z>UsIm%Dpmaj8f0yg+@;KL@K`z#DW93LI5~{8`uHJ(w4{o0Q?t8mP&;gnKF*AL?TM# zaK(Jv=^O_;duM=z#3atduYJb`1OO2B)hR9eDS(>?0Qzo9ONj+&P6nV`Pia=w0BS;j z^9;URnm?i8008hn0S2%@3-rMlEWidFz!^Ni2Ld4!A|M75VFBhQ^@t(F`;fEkKLVO=tyLgC0g(&~xZD^fszMU!kKIU{s8a8Dch=E9Q?y zU`bdyCdF1@C0IFDgEeC9SQmB^Q((i`XB+{?#Bp#oI1gM1E*8hf<>FT0HsUIAb+{JX z1>8+sKW+r~9Z$#W;;r%ScrHExpMhVDFUFVS58#{e7xB08gZK{w0)b61C%6zo2#JI& z!ZN}}!X82sp@Yyz7$A%ii9{`;HPMq8LF5r-#A4zu;$h-h;tk>;@e_$kG9WpSf=Edu zF=-8{oOFnEhIE7UoHRyOC7Y7n$q{4$c`11_xt82czD^z_k5SYp<`hp#3?+-Qno>b& zq+FytqP(M0sYX;c>RhUjx{6vsJxaYy?WcaGsne`z{KTm%`|D?iHu~p%!2vk<8RH?M6+)#PVATvxEzKjKo0!BIGIO95FSe2}5 zrs}WCQ(d82rFv5JuIi{7Q_Ws2LM=yaquL?0D{3#)iRxzRf$9SFBK7_1=hX+87}J>P z&*U@LGHaO^nS(3>%bdk!WwAXnHq5#OEju9PHQOG7~71^WsBIG*~i#- z*k7jUP4k_WHf_VS#%VXEebm&^^wCVyEYWPzysh~~i=!2&m94c^t5xf%I>$CNJ^t1H0 z>z~mdGGH2b83+xw8=N(G$*MCbLZnO&Uxdn37FhO*2h*ns%9fG&47gH(PJkYWBih)0}HwVBTQ< z$bxR+ZINqHV{yxpVCia^ZMny?*9x_AvdXlovbt`KT02_{t@l{>O~+4nn=YPSGySd& z&BoUz-=@K)-<4VUi$2T*rXQs{EJM*3s(`mNTdZ$jOZ_X~xQs+kJAr}*u6qnsDcU@Vo zk**tEFT3I0{M=T$opSr^?(8meKj!|IhmA+J$03gwv&?6u&8nR>;A!N^^W5jD@Zxx- zc>Uz1@HX`3dDnP9^)dDl_#E(g?rZ6r<$KuowV$1z)UVm^qrbcVa{rD1EFd_bB%miy zJuo(~GVn=|QBX!uL(oXDQ}D9jju3oESjg6pyIegkpIgrz33Ulw9(o~+78V^=8TK^X zDqI@gJ{z4KI(ysfM{`W)i08CMKm<2pTg2l?^T^!DU*{6$M$WC8`z*>nsxYc6ni;(? z`cU+T7{8d!F%M%cV&$=&ag4a+xcaz{@d5E=@rr~Q3Ck0%C2A)M6WfxANpVRBl1AqR z&f76>Fxe@&IQhImPT zzmxw;;3L>B7)tX@D@%Kx?wMYe{vyLOV_U{hrgvs}=CIITSSfsy6_Qn*^)Wjl`(XCC zC|=Z*L&{0XIVn~bXNxZ^(qFV>QJ=(GQY=yAy65i59g&7f59A?v^YhwdESW^sEw_-b zllSL)+h8rmW6h{o5M5HDznwuZ>^ZUZhvFs%T(c@VbU#m11e}-Sr;ptAD`# zApD_cgX4x>8@`taO0JgLm6n%&-N@f~^+)?3D}Ef`l)kBFv-9S?TL@dkTkdT2-db0t zR#s3pux<9XmhGJFCEMTcSh(X#`ONa_os^yOor;R^ind)QySD85TA5jSyUMSsX}9j~ z4ZARsyV59uD-+<-R78-@-iAMQO8aHOr#rg2{ryQ%aj9F-q^`Af<#caDV} z>pbpyyzzwTiQUc2=8_hqWogSuYi6sWEwQcdWa!Dxc8~VvUu}Oqc*^ip)oG2>o6k_r z6rCAATX1%?L((yPF5}!l=fcj1=M&D~x-j=b&&9BdmoEifI^X5nb@sC7t8s$I5iYB)cbPY%fVNYS7XD)f2#et`?baE6My;q)jg6h zGWbUNX8i5OcUtcbzMuKNb2M`F$%mW|V;@UCX??2u?E1OuOZ=DTV~f8MzgB#+{MP