1 // ---------------------------------------------------------------------------
4 // @author Philippe Decaudin - http://www.antisphere.com
5 // @license This file is part of the AntTweakBar library.
6 // For conditions of distribution and use, see License.txt
8 // ---------------------------------------------------------------------------
11 #include "TwPrecomp.h"
12 #include <AntTweakBar.h>
19 extern const char *g_ErrNotFound;
20 const char *g_ErrUnknownAttrib = "Unknown parameter";
21 const char *g_ErrInvalidAttrib = "Invalid parameter";
22 const char *g_ErrNotGroup = "Value is not a group";
23 const char *g_ErrNoValue = "Value required";
24 const char *g_ErrBadValue = "Bad value";
25 const char *g_ErrUnknownType = "Unknown type";
26 const char *g_ErrNotEnum = "Must be of type Enum";
28 #undef PERF // comment to print benchs
34 #define ANT_SET_CURSOR(_Name) g_TwMgr->SetCursor(g_TwMgr->m_Cursor##_Name)
35 #define ANT_SET_ROTO_CURSOR(_Num) g_TwMgr->SetCursor(g_TwMgr->m_RotoCursors[_Num])
37 #if !defined(ANT_WINDOWS)
38 # define _stricmp strcasecmp
39 # define _strdup strdup
40 #endif // defined(ANT_WINDOWS)
43 # define M_PI 3.1415926535897932384626433832795
44 #endif // !defined(M_PI)
46 const float FLOAT_MAX = 3.0e+38f;
47 const double DOUBLE_MAX = 1.0e+308;
48 const double DOUBLE_EPS = 1.0e-307;
50 bool IsCustomType(int _Type)
52 return (g_TwMgr && _Type>=TW_TYPE_CUSTOM_BASE && _Type<TW_TYPE_CUSTOM_BASE+(int)g_TwMgr->m_Customs.size());
55 bool IsCSStringType(int _Type)
57 return (_Type>TW_TYPE_CSSTRING_BASE && _Type<=TW_TYPE_CSSTRING_MAX);
60 bool IsEnumType(int _Type)
62 return (g_TwMgr && _Type>=TW_TYPE_ENUM_BASE && _Type<TW_TYPE_ENUM_BASE+(int)g_TwMgr->m_Enums.size());
65 // ---------------------------------------------------------------------------
74 m_ColorPtr = &COLOR32_WHITE;
75 m_BgColorPtr = &COLOR32_ZERO; // default
78 CTwVarAtom::CTwVarAtom()
80 m_Type = TW_TYPE_UNDEF;
91 memset(&m_Val, 0, sizeof(UVal));
94 CTwVarAtom::~CTwVarAtom()
96 if( m_Type==TW_TYPE_BOOL8 || m_Type==TW_TYPE_BOOL16 || m_Type==TW_TYPE_BOOL32 || m_Type==TW_TYPE_BOOLCPP )
98 if( m_Val.m_Bool.m_FreeTrueString && m_Val.m_Bool.m_TrueString!=NULL )
100 free(m_Val.m_Bool.m_TrueString);
101 m_Val.m_Bool.m_TrueString = NULL;
103 if( m_Val.m_Bool.m_FreeFalseString && m_Val.m_Bool.m_FalseString!=NULL )
105 free(m_Val.m_Bool.m_FalseString);
106 m_Val.m_Bool.m_FalseString = NULL;
109 else if( m_Type==TW_TYPE_CDSTDSTRING && m_GetCallback==CTwMgr::CCDStdString::GetCB && m_ClientData!=NULL && g_TwMgr!=NULL )
111 // delete corresponding g_TwMgr->m_CDStdStrings element
112 const CTwMgr::CCDStdString *CDStdString = (const CTwMgr::CCDStdString *)m_ClientData;
113 //if( &(*CDStdString->m_This)==CDStdString )
114 // g_TwMgr->m_CDStdStrings.erase(CDStdString->m_This);
115 for( list<CTwMgr::CCDStdString>::iterator it=g_TwMgr->m_CDStdStrings.begin(); it!=g_TwMgr->m_CDStdStrings.end(); ++it )
116 if( &(*it)==CDStdString )
118 g_TwMgr->m_CDStdStrings.erase(it);
123 else if( m_Type==TW_TYPE_ENUM8 || m_Type==TW_TYPE_ENUM16 || m_Type==TW_TYPE_ENUM32 )
125 if( m_Val.m_Enum.m_Entries!=NULL )
127 delete m_Val.m_Enum.m_Entries;
128 m_Val.m_Enum.m_Entries = NULL;
134 // ---------------------------------------------------------------------------
136 void CTwVarAtom::ValueToString(string *_Str) const
139 static const char *ErrStr = "unreachable";
141 if( m_Type==TW_TYPE_UNDEF || m_Type==TW_TYPE_HELP_ATOM || m_Type==TW_TYPE_HELP_GRP || m_Type==TW_TYPE_BUTTON ) // has no value
146 else if( m_Type==TW_TYPE_HELP_HEADER )
151 else if( m_Type==TW_TYPE_SHORTCUT ) // special case for help bar: display shortcut
154 if( m_ReadOnly && m_Val.m_Shortcut.m_Incr[0]==0 && m_Val.m_Shortcut.m_Decr[0]==0 )
155 (*_Str) = "(read only)";
158 if( m_Val.m_Shortcut.m_Incr[0]>0 )
159 TwGetKeyString(_Str, m_Val.m_Shortcut.m_Incr[0], m_Val.m_Shortcut.m_Incr[1]);
162 if( m_Val.m_Shortcut.m_Decr[0]>0 )
165 TwGetKeyString(_Str, m_Val.m_Shortcut.m_Decr[0], m_Val.m_Shortcut.m_Decr[1]);
170 else if( m_Type==TW_TYPE_HELP_STRUCT )
172 int idx = m_Val.m_HelpStruct.m_StructType - TW_TYPE_STRUCT_BASE;
173 if( idx>=0 && idx<(int)g_TwMgr->m_Structs.size() )
175 if( g_TwMgr->m_Structs[idx].m_Name.length()>0 )
176 (*_Str) = '{' + g_TwMgr->m_Structs[idx].m_Name + '}';
178 (*_Str) = "{struct}";
183 if( m_Ptr==NULL && m_GetCallback==NULL )
188 bool UseGet = (m_GetCallback!=NULL);
191 case TW_TYPE_BOOLCPP:
195 m_GetCallback(&Val, m_ClientData);
197 Val = *(bool *)m_Ptr;
199 *_Str = (m_Val.m_Bool.m_TrueString!=NULL) ? m_Val.m_Bool.m_TrueString : "1";
201 *_Str = (m_Val.m_Bool.m_FalseString!=NULL) ? m_Val.m_Bool.m_FalseString : "0";
208 m_GetCallback(&Val, m_ClientData);
210 Val = *(char *)m_Ptr;
212 *_Str = (m_Val.m_Bool.m_TrueString!=NULL) ? m_Val.m_Bool.m_TrueString : "1";
214 *_Str = (m_Val.m_Bool.m_FalseString!=NULL) ? m_Val.m_Bool.m_FalseString : "0";
221 m_GetCallback(&Val, m_ClientData);
223 Val = *(short *)m_Ptr;
225 *_Str = (m_Val.m_Bool.m_TrueString!=NULL) ? m_Val.m_Bool.m_TrueString : "1";
227 *_Str = (m_Val.m_Bool.m_FalseString!=NULL) ? m_Val.m_Bool.m_FalseString : "0";
234 m_GetCallback(&Val, m_ClientData);
238 *_Str = (m_Val.m_Bool.m_TrueString!=NULL) ? m_Val.m_Bool.m_TrueString : "1";
240 *_Str = (m_Val.m_Bool.m_FalseString!=NULL) ? m_Val.m_Bool.m_FalseString : "0";
245 unsigned char Val = 0;
247 m_GetCallback(&Val, m_ClientData);
249 Val = *(unsigned char *)m_Ptr;
253 if( m_Val.m_Char.m_Hexa )
254 sprintf(Tmp, "%c (0x%.2X)", Val, d);
256 sprintf(Tmp, "%c (%d)", Val, d);
262 const_cast<char *>(_Str->c_str())[0] = '\0';
270 m_GetCallback(&Val, m_ClientData);
272 Val = *(signed char *)m_Ptr;
274 if( m_Val.m_Int8.m_Hexa )
275 sprintf(Tmp, "0x%.2X", d&0xff);
277 sprintf(Tmp, "%d", d);
283 unsigned char Val = 0;
285 m_GetCallback(&Val, m_ClientData);
287 Val = *(unsigned char *)m_Ptr;
288 unsigned int d = Val;
289 if( m_Val.m_UInt8.m_Hexa )
290 sprintf(Tmp, "0x%.2X", d);
292 sprintf(Tmp, "%u", d);
300 m_GetCallback(&Val, m_ClientData);
302 Val = *(short *)m_Ptr;
304 if( m_Val.m_Int16.m_Hexa )
305 sprintf(Tmp, "0x%.4X", d&0xffff);
307 sprintf(Tmp, "%d", d);
313 unsigned short Val = 0;
315 m_GetCallback(&Val, m_ClientData);
317 Val = *(unsigned short *)m_Ptr;
318 unsigned int d = Val;
319 if( m_Val.m_UInt16.m_Hexa )
320 sprintf(Tmp, "0x%.4X", d);
322 sprintf(Tmp, "%u", d);
330 m_GetCallback(&Val, m_ClientData);
333 if( m_Val.m_Int32.m_Hexa )
334 sprintf(Tmp, "0x%.8X", Val);
336 sprintf(Tmp, "%d", Val);
342 unsigned int Val = 0;
344 m_GetCallback(&Val, m_ClientData);
346 Val = *(unsigned int *)m_Ptr;
347 if( m_Val.m_UInt32.m_Hexa )
348 sprintf(Tmp, "0x%.8X", Val);
350 sprintf(Tmp, "%u", Val);
358 m_GetCallback(&Val, m_ClientData);
360 Val = *(float *)m_Ptr;
361 if( m_Val.m_Float32.m_Precision<0 )
362 sprintf(Tmp, "%g", Val);
366 sprintf(Fmt, "%%.%df", (int)m_Val.m_Float32.m_Precision);
367 sprintf(Tmp, Fmt, Val);
376 m_GetCallback(&Val, m_ClientData);
378 Val = *(double *)m_Ptr;
379 if( m_Val.m_Float64.m_Precision<0 )
380 sprintf(Tmp, "%g", Val);
384 sprintf(Fmt, "%%.%dlf", (int)m_Val.m_Float64.m_Precision);
385 sprintf(Tmp, Fmt, Val);
390 case TW_TYPE_STDSTRING:
393 m_GetCallback(_Str, m_ClientData);
395 *_Str = *(std::string *)m_Ptr;
404 if( m_Type==TW_TYPE_ENUM8 )
406 unsigned char Val = 0;
408 m_GetCallback(&Val, m_ClientData);
410 Val = *(unsigned char *)m_Ptr;
413 else if( m_Type==TW_TYPE_ENUM16 )
415 unsigned short Val = 0;
417 m_GetCallback(&Val, m_ClientData);
419 Val = *(unsigned short *)m_Ptr;
424 assert(m_Type==TW_TYPE_ENUM32);
425 unsigned int Val = 0;
427 m_GetCallback(&Val, m_ClientData);
429 Val = *(unsigned int *)m_Ptr;
433 if( m_Val.m_Enum.m_Entries!=NULL )
435 UVal::CEnumVal::CEntries::iterator It = m_Val.m_Enum.m_Entries->find(d);
436 if( It!=m_Val.m_Enum.m_Entries->end() )
444 sprintf(Tmp, "%u", d);
451 if( IsEnumType(m_Type) )
453 unsigned int Val = 0;
455 m_GetCallback(&Val, m_ClientData);
457 Val = *(unsigned int *)m_Ptr;
459 CTwMgr::CEnum& e = g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE];
460 CTwMgr::CEnum::CEntries::iterator It = e.m_Entries.find(Val);
461 if( It!=e.m_Entries.end() )
465 sprintf(Tmp, "%u", Val);
469 else if( IsCSStringType(m_Type) )
474 int n = TW_CSSTRING_SIZE(m_Type);
475 if( n+32>(int)g_TwMgr->m_CSStringBuffer.size() )
476 g_TwMgr->m_CSStringBuffer.resize(n+32);
477 Val = &(g_TwMgr->m_CSStringBuffer[0]);
478 m_GetCallback(Val , m_ClientData);
488 else if( m_Type==TW_TYPE_CDSTRING || m_Type==TW_TYPE_CDSTDSTRING )
492 m_GetCallback(&Val , m_ClientData);
494 Val = *(char **)m_Ptr;
500 else if( IsCustom() ) // m_Type>=TW_TYPE_CUSTOM_BASE && m_Type<TW_TYPE_CUSTOM_BASE+(int)g_TwMgr->m_Customs.size() )
506 *_Str = "unknown type";
507 const_cast<CTwVarAtom *>(this)->m_ReadOnly = true;
512 // ---------------------------------------------------------------------------
514 double CTwVarAtom::ValueToDouble() const
516 if( m_Ptr==NULL && m_GetCallback==NULL )
517 return 0; // unreachable
518 bool UseGet = (m_GetCallback!=NULL);
521 case TW_TYPE_BOOLCPP:
525 m_GetCallback(&Val, m_ClientData);
527 Val = *(bool *)m_Ptr;
538 m_GetCallback(&Val, m_ClientData);
540 Val = *(char *)m_Ptr;
551 m_GetCallback(&Val, m_ClientData);
553 Val = *(short *)m_Ptr;
564 m_GetCallback(&Val, m_ClientData);
575 unsigned char Val = 0;
577 m_GetCallback(&Val, m_ClientData);
579 Val = *(unsigned char *)m_Ptr;
587 m_GetCallback(&Val, m_ClientData);
589 Val = *(signed char *)m_Ptr;
596 unsigned char Val = 0;
598 m_GetCallback(&Val, m_ClientData);
600 Val = *(unsigned char *)m_Ptr;
601 unsigned int d = Val;
609 m_GetCallback(&Val, m_ClientData);
611 Val = *(short *)m_Ptr;
618 unsigned short Val = 0;
620 m_GetCallback(&Val, m_ClientData);
622 Val = *(unsigned short *)m_Ptr;
623 unsigned int d = Val;
631 m_GetCallback(&Val, m_ClientData);
639 unsigned int Val = 0;
641 m_GetCallback(&Val, m_ClientData);
643 Val = *(unsigned int *)m_Ptr;
651 m_GetCallback(&Val, m_ClientData);
653 Val = *(float *)m_Ptr;
661 m_GetCallback(&Val, m_ClientData);
663 Val = *(double *)m_Ptr;
673 if( m_Type==TW_TYPE_ENUM8 )
675 unsigned char Val = 0;
677 m_GetCallback(&Val, m_ClientData);
679 Val = *(unsigned char *)m_Ptr;
682 else if( m_Type==TW_TYPE_ENUM16 )
684 unsigned short Val = 0;
686 m_GetCallback(&Val, m_ClientData);
688 Val = *(unsigned short *)m_Ptr;
693 assert(m_Type==TW_TYPE_ENUM32);
694 unsigned int Val = 0;
696 m_GetCallback(&Val, m_ClientData);
698 Val = *(unsigned int *)m_Ptr;
706 if( IsEnumType(m_Type) )
708 unsigned int Val = 0;
710 m_GetCallback(&Val, m_ClientData);
712 Val = *(unsigned int *)m_Ptr;
716 return 0; // unknown type
720 // ---------------------------------------------------------------------------
722 void CTwVarAtom::ValueFromDouble(double _Val)
724 if( m_Ptr==NULL && m_SetCallback==NULL )
725 return; // unreachable
726 bool UseSet = (m_SetCallback!=NULL);
729 case TW_TYPE_BOOLCPP:
731 bool Val = (_Val!=0);
733 m_SetCallback(&Val, m_ClientData);
740 char Val = (_Val!=0) ? 1 : 0;
742 m_SetCallback(&Val, m_ClientData);
749 short Val = (_Val!=0) ? 1 : 0;
751 m_SetCallback(&Val, m_ClientData);
753 *(short*)m_Ptr = Val;
758 int Val = (_Val!=0) ? 1 : 0;
760 m_SetCallback(&Val, m_ClientData);
767 unsigned char Val = (unsigned char)_Val;
769 m_SetCallback(&Val, m_ClientData);
771 *(unsigned char*)m_Ptr = Val;
776 signed char Val = (signed char)_Val;
778 m_SetCallback(&Val, m_ClientData);
780 *(signed char*)m_Ptr = Val;
784 //case TW_TYPE_ENUM8:
786 unsigned char Val = (unsigned char)_Val;
788 m_SetCallback(&Val, m_ClientData);
790 *(unsigned char*)m_Ptr = Val;
795 short Val = (short)_Val;
797 m_SetCallback(&Val, m_ClientData);
799 *(short*)m_Ptr = Val;
803 //case TW_TYPE_ENUM16:
805 unsigned short Val = (unsigned short)_Val;
807 m_SetCallback(&Val, m_ClientData);
809 *(unsigned short*)m_Ptr = Val;
816 m_SetCallback(&Val, m_ClientData);
822 //case TW_TYPE_ENUM32:
824 unsigned int Val = (unsigned int)_Val;
826 m_SetCallback(&Val, m_ClientData);
828 *(unsigned int*)m_Ptr = Val;
833 float Val = (float)_Val;
835 m_SetCallback(&Val, m_ClientData);
837 *(float*)m_Ptr = Val;
842 double Val = (double)_Val;
844 m_SetCallback(&Val, m_ClientData);
846 *(double*)m_Ptr = Val;
850 if( IsEnumType(m_Type) )
852 unsigned int Val = (unsigned int)_Val;
854 m_SetCallback(&Val, m_ClientData);
856 *(unsigned int*)m_Ptr = Val;
861 // ---------------------------------------------------------------------------
863 void CTwVarAtom::MinMaxStepToDouble(double *_Min, double *_Max, double *_Step) const
865 double max = DOUBLE_MAX;
866 double min = -DOUBLE_MAX;
871 case TW_TYPE_BOOLCPP:
880 min = (double)m_Val.m_Char.m_Min;
881 max = (double)m_Val.m_Char.m_Max;
882 step = (double)m_Val.m_Char.m_Step;
885 min = (double)m_Val.m_Int8.m_Min;
886 max = (double)m_Val.m_Int8.m_Max;
887 step = (double)m_Val.m_Int8.m_Step;
890 min = (double)m_Val.m_UInt8.m_Min;
891 max = (double)m_Val.m_UInt8.m_Max;
892 step = (double)m_Val.m_UInt8.m_Step;
895 min = (double)m_Val.m_Int16.m_Min;
896 max = (double)m_Val.m_Int16.m_Max;
897 step = (double)m_Val.m_Int16.m_Step;
900 min = (double)m_Val.m_UInt16.m_Min;
901 max = (double)m_Val.m_UInt16.m_Max;
902 step = (double)m_Val.m_UInt16.m_Step;
905 min = (double)m_Val.m_Int32.m_Min;
906 max = (double)m_Val.m_Int32.m_Max;
907 step = (double)m_Val.m_Int32.m_Step;
910 min = (double)m_Val.m_UInt32.m_Min;
911 max = (double)m_Val.m_UInt32.m_Max;
912 step = (double)m_Val.m_UInt32.m_Step;
915 min = (double)m_Val.m_Float32.m_Min;
916 max = (double)m_Val.m_Float32.m_Max;
917 step = (double)m_Val.m_Float32.m_Step;
920 min = m_Val.m_Float64.m_Min;
921 max = m_Val.m_Float64.m_Max;
922 step = m_Val.m_Float64.m_Step;
936 // ---------------------------------------------------------------------------
938 const CTwVar *CTwVarAtom::Find(const char *_Name, CTwVarGroup **_Parent, int *_Index) const
940 if( strcmp(_Name, m_Name.c_str())==0 )
952 // ---------------------------------------------------------------------------
968 int CTwVar::HasAttrib(const char *_Attrib, bool *_HasValue) const
971 if( _stricmp(_Attrib, "label")==0 )
973 else if( _stricmp(_Attrib, "help")==0 )
975 else if( _stricmp(_Attrib, "group")==0 )
977 else if( _stricmp(_Attrib, "order")==0 )
979 else if( _stricmp(_Attrib, "visible")==0 )
981 else if( _stricmp(_Attrib, "readonly")==0 )
984 // for backward compatibility
986 if( _stricmp(_Attrib, "show")==0 )
988 else if( _stricmp(_Attrib, "hide")==0 )
990 if( _stricmp(_Attrib, "readonly")==0 )
992 else if( _stricmp(_Attrib, "readwrite")==0 )
995 return 0; // not found
998 int CTwVar::SetAttrib(int _AttribID, const char *_Value, TwBar *_Bar, struct CTwVarGroup *_VarParent, int _VarIndex)
1004 if( _Value && strlen(_Value)>0 )
1007 if( IsGroup() && static_cast<CTwVarGroup *>(this)->m_StructValuePtr!=NULL )
1009 int Idx = static_cast<CTwVarGroup *>(this)->m_StructType-TW_TYPE_STRUCT_BASE;
1010 if( Idx>=0 && Idx<(int)g_TwMgr->m_Structs.size() )
1011 if( _AttribID==V_LABEL )
1012 g_TwMgr->m_Structs[Idx].m_Label = _Value;
1014 g_TwMgr->m_Structs[Idx].m_Help = _Value;
1019 CTwVarGroup *Parent = NULL;
1020 CTwVar *ThisVar = _Bar->Find(m_Name.c_str(), &Parent);
1021 if( this==ThisVar && Parent!=NULL && Parent->m_StructValuePtr!=NULL )
1023 int Idx = Parent->m_StructType-TW_TYPE_STRUCT_BASE;
1024 if( Idx>=0 && Idx<(int)g_TwMgr->m_Structs.size() )
1026 size_t nl = m_Name.length();
1027 for( size_t im=0; im<g_TwMgr->m_Structs[Idx].m_Members.size(); ++im )
1029 size_t ml = g_TwMgr->m_Structs[Idx].m_Members[im].m_Name.length();
1030 if( nl>=ml && strcmp(g_TwMgr->m_Structs[Idx].m_Members[im].m_Name.c_str(), m_Name.c_str()+(nl-ml))==0 )
1032 // TODO: would have to be applied to other vars already created
1033 if( _AttribID==V_LABEL )
1035 g_TwMgr->m_Structs[Idx].m_Members[im].m_Label = _Value;
1036 // m_Label = _Value;
1039 g_TwMgr->m_Structs[Idx].m_Members[im].m_Help = _Value;
1047 if( _AttribID==V_LABEL )
1053 _Bar->NotUpToDate();
1058 g_TwMgr->SetLastError(g_ErrNoValue);
1063 CTwVarGroup *Grp = NULL;
1064 if( _Value==NULL || strlen(_Value)<=0 )
1065 Grp = &(_Bar->m_VarRoot);
1068 CTwVar *v = _Bar->Find(_Value, NULL, NULL);
1069 if( v && !v->IsGroup() )
1071 g_TwMgr->SetLastError(g_ErrNotGroup);
1074 Grp = static_cast<CTwVarGroup *>(v);
1077 Grp = new CTwVarGroup;
1078 Grp->m_Name = _Value;
1080 Grp->m_SummaryCallback = NULL;
1081 Grp->m_SummaryClientData = NULL;
1082 Grp->m_StructValuePtr = NULL;
1083 Grp->m_ColorPtr = &(_Bar->m_ColGrpText);
1084 _Bar->m_VarRoot.m_Vars.push_back(Grp);
1087 Grp->m_Vars.push_back(this);
1088 if( _VarParent!=NULL && _VarIndex>=0 )
1090 _VarParent->m_Vars.erase(_VarParent->m_Vars.begin()+_VarIndex);
1091 if( _VarParent!=&(_Bar->m_VarRoot) && _VarParent->m_Vars.size()<=0 )
1092 TwRemoveVar(_Bar, _VarParent->m_Name.c_str());
1094 _Bar->NotUpToDate();
1097 case V_SHOW: // for backward compatibility
1101 _Bar->NotUpToDate();
1104 case V_HIDE: // for backward compatibility
1108 _Bar->NotUpToDate();
1114 _Bar->NotUpToDate();
1117 case V_READWRITE: // for backward compatibility
1119 _Bar->NotUpToDate();
1122 // a special case for compatibility with deprecated command 'option=ogl/dx'
1123 if( IsGroup() && _Value!=NULL && static_cast<CTwVarGroup *>(this)->m_SummaryCallback==CColorExt::SummaryCB && static_cast<CTwVarGroup *>(this)->m_StructValuePtr!=NULL ) // is tw_type_color?
1125 if( _stricmp(_Value, "ogl")==0 )
1127 static_cast<CColorExt *>(static_cast<CTwVarGroup *>(this)->m_StructValuePtr)->m_OGL = true;
1130 else if( _stricmp(_Value, "dx")==0 )
1132 static_cast<CColorExt *>(static_cast<CTwVarGroup *>(this)->m_StructValuePtr)->m_OGL = false;
1136 // todo: general 'order' command (no else)
1139 if( _Value!=NULL && strlen(_Value)>0 )
1141 if( _stricmp(_Value, "true")==0 || _stricmp(_Value, "1")==0 )
1146 _Bar->NotUpToDate();
1150 else if( _stricmp(_Value, "false")==0 || _stricmp(_Value, "0")==0 )
1155 _Bar->NotUpToDate();
1161 g_TwMgr->SetLastError(g_ErrBadValue);
1167 g_TwMgr->SetLastError(g_ErrNoValue);
1171 if( _Value==NULL || strlen(_Value)==0 // no value is acceptable (for backward compatibility)
1172 || _stricmp(_Value, "true")==0 || _stricmp(_Value, "1")==0 )
1177 _Bar->NotUpToDate();
1181 else if( _stricmp(_Value, "false")==0 || _stricmp(_Value, "0")==0 )
1186 _Bar->NotUpToDate();
1192 g_TwMgr->SetLastError(g_ErrBadValue);
1196 g_TwMgr->SetLastError(g_ErrUnknownAttrib);
1202 ERetType CTwVar::GetAttrib(int _AttribID, TwBar * /*_Bar*/, CTwVarGroup * _VarParent, int /*_VarIndex*/, std::vector<double>& outDoubles, std::ostringstream& outString) const
1210 outString << m_Label;
1213 outString << m_Help;
1216 if( _VarParent!=NULL )
1217 outString << _VarParent->m_Name;
1220 outDoubles.push_back(m_Visible ? 1 : 0);
1223 outDoubles.push_back(IsReadOnly() ? 1 : 0);
1226 g_TwMgr->SetLastError(g_ErrUnknownAttrib);
1232 // ---------------------------------------------------------------------------
1234 enum EVarAtomAttribs
1236 VA_KEY_INCR = V_ENDTAG+1,
1243 VA_DECIMAL, // for backward compatibility
1250 int CTwVarAtom::HasAttrib(const char *_Attrib, bool *_HasValue) const
1253 if( _stricmp(_Attrib, "keyincr")==0 || _stricmp(_Attrib, "key")==0 )
1255 else if( _stricmp(_Attrib, "keydecr")==0 )
1257 else if( _stricmp(_Attrib, "min")==0 )
1259 else if( _stricmp(_Attrib, "max")==0 )
1261 else if( _stricmp(_Attrib, "step")==0 )
1263 else if( _stricmp(_Attrib, "precision")==0 )
1264 return VA_PRECISION;
1265 else if( _stricmp(_Attrib, "hexa")==0 )
1267 else if( _stricmp(_Attrib, "decimal")==0 ) // for backward compatibility
1272 else if( _stricmp(_Attrib, "true")==0 )
1274 else if( _stricmp(_Attrib, "false")==0 )
1276 else if( _stricmp(_Attrib, "enum")==0
1277 || _stricmp(_Attrib, "val")==0 ) // for backward compatibility
1279 else if( _stricmp(_Attrib, "value")==0 )
1282 return CTwVar::HasAttrib(_Attrib, _HasValue);
1285 int CTwVarAtom::SetAttrib(int _AttribID, const char *_Value, TwBar *_Bar, struct CTwVarGroup *_VarParent, int _VarIndex)
1293 if( TwGetKeyCode(&Key, &Mod, _Value) )
1306 if( TwGetKeyCode(&Key, &Mod, _Value) )
1316 if( (m_Type==TW_TYPE_BOOL8 || m_Type==TW_TYPE_BOOL16 || m_Type==TW_TYPE_BOOL32 || m_Type==TW_TYPE_BOOLCPP) && _Value!=NULL )
1318 if( m_Val.m_Bool.m_FreeTrueString && m_Val.m_Bool.m_TrueString!=NULL )
1319 free(m_Val.m_Bool.m_TrueString);
1320 m_Val.m_Bool.m_TrueString = _strdup(_Value);
1321 m_Val.m_Bool.m_FreeTrueString = true;
1327 if( (m_Type==TW_TYPE_BOOL8 || m_Type==TW_TYPE_BOOL16 || m_Type==TW_TYPE_BOOL32 || m_Type==TW_TYPE_BOOLCPP) && _Value!=NULL )
1329 if( m_Val.m_Bool.m_FreeFalseString && m_Val.m_Bool.m_FalseString!=NULL )
1330 free(m_Val.m_Bool.m_FalseString);
1331 m_Val.m_Bool.m_FalseString = _strdup(_Value);
1332 m_Val.m_Bool.m_FreeFalseString = true;
1340 if( _Value && strlen(_Value)>0 )
1343 const char *Fmt = NULL;
1346 int Num = (_AttribID==VA_STEP) ? 2 : ((_AttribID==VA_MAX) ? 1 : 0);
1350 //Ptr = (&m_Val.m_Char.m_Min) + Num;
1356 Ptr = (&m_Val.m_Int16.m_Min) + Num;
1360 Ptr = (&m_Val.m_Int32.m_Min) + Num;
1363 case TW_TYPE_UINT16:
1364 Ptr = (&m_Val.m_UInt16.m_Min) + Num;
1367 case TW_TYPE_UINT32:
1368 Ptr = (&m_Val.m_UInt32.m_Min) + Num;
1372 Ptr = (&m_Val.m_Float32.m_Min) + Num;
1375 case TW_TYPE_DOUBLE:
1376 Ptr = (&m_Val.m_Float64.m_Min) + Num;
1388 g_TwMgr->SetLastError(g_ErrUnknownType);
1392 if( Fmt!=NULL && Ptr!=NULL && sscanf(_Value, Fmt, Ptr)==1 )
1394 if( m_Type==TW_TYPE_CHAR )
1395 *((&m_Val.m_Char.m_Min)+Num) = (unsigned char)(u);
1396 else if( m_Type==TW_TYPE_INT8 )
1397 *((&m_Val.m_Int8.m_Min)+Num) = (signed char)(d);
1398 else if( m_Type==TW_TYPE_UINT8 )
1399 *((&m_Val.m_UInt8.m_Min)+Num) = (unsigned char)(u);
1402 if( _AttribID==VA_STEP && ((m_Type==TW_TYPE_FLOAT && m_Val.m_Float32.m_Precision<0) || (m_Type==TW_TYPE_DOUBLE && m_Val.m_Float64.m_Precision<0)) )
1404 double Step = fabs( (m_Type==TW_TYPE_FLOAT) ? m_Val.m_Float32.m_Step : m_Val.m_Float64.m_Step );
1405 signed char *Precision = (m_Type==TW_TYPE_FLOAT) ? &m_Val.m_Float32.m_Precision : &m_Val.m_Float64.m_Precision;
1406 const double K_EPS = 1.0 - 1.0e-6;
1409 else if( Step>=0.1*K_EPS )
1411 else if( Step>=0.01*K_EPS )
1413 else if( Step>=0.001*K_EPS )
1415 else if( Step>=0.0001*K_EPS )
1417 else if( Step>=0.00001*K_EPS )
1419 else if( Step>=0.000001*K_EPS )
1421 else if( Step>=0.0000001*K_EPS )
1423 else if( Step>=0.00000001*K_EPS )
1425 else if( Step>=0.000000001*K_EPS )
1427 else if( Step>=0.0000000001*K_EPS )
1429 else if( Step>=0.00000000001*K_EPS )
1431 else if( Step>=0.000000000001*K_EPS )
1441 g_TwMgr->SetLastError(g_ErrBadValue);
1447 g_TwMgr->SetLastError(g_ErrNoValue);
1451 if( _Value && strlen(_Value)>0 )
1454 if( sscanf(_Value, "%d", &Precision)==1 && Precision>=-1 && Precision<=12 )
1456 if( m_Type==TW_TYPE_FLOAT )
1457 m_Val.m_Float32.m_Precision = (signed char)Precision;
1458 else if ( m_Type==TW_TYPE_DOUBLE )
1459 m_Val.m_Float64.m_Precision = (signed char)Precision;
1464 g_TwMgr->SetLastError(g_ErrBadValue);
1470 g_TwMgr->SetLastError(g_ErrNoValue);
1477 if (_AttribID==VA_HEXA)
1479 if( _Value==NULL || strlen(_Value)==0 // no value is acceptable (for backward compatibility)
1480 || _stricmp(_Value, "true")==0 || _stricmp(_Value, "1")==0 )
1487 m_Val.m_Char.m_Hexa = hexa;
1490 m_Val.m_Int8.m_Hexa = hexa;
1493 m_Val.m_Int16.m_Hexa = hexa;
1496 m_Val.m_Int32.m_Hexa = hexa;
1499 m_Val.m_UInt8.m_Hexa = hexa;
1501 case TW_TYPE_UINT16:
1502 m_Val.m_UInt16.m_Hexa = hexa;
1504 case TW_TYPE_UINT32:
1505 m_Val.m_UInt32.m_Hexa = hexa;
1512 if( _Value && strlen(_Value)>0 && IsEnumType(m_Type) )
1514 const char *s = _Value;
1518 g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE].m_Entries.clear(); // anyway reset entries
1524 n = sscanf(s, "%u %c%n", &u, &Sep, &i);
1525 if( n==2 && i>0 && ( Sep=='<' || Sep=='{' || Sep=='[' || Sep=='(' ) )
1527 if( Sep=='<' ) // Change to closing separator
1537 while( s[i]!=Sep && s[i]!=0 )
1541 //if( m_Val.m_Enum.m_Entries==NULL )
1542 // m_Val.m_Enum.m_Entries = new UVal::CEnumVal::CEntries;
1543 //UVal::CEnumVal::CEntries::value_type v(u, "");
1544 CTwMgr::CEnum::CEntries::value_type v(u, "");
1546 v.second.assign(s, i);
1547 //m_Val.m_Enum.m_Entries->insert(v);
1548 pair<CTwMgr::CEnum::CEntries::iterator, bool> ret;
1549 ret = g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE].m_Entries.insert(v);
1550 if( !ret.second ) // force overwrite if element already exists
1552 g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE].m_Entries.erase(ret.first);
1553 g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE].m_Entries.insert(v);
1558 n = sscanf(s, " ,%n", &i);
1567 g_TwMgr->SetLastError(g_ErrBadValue);
1573 g_TwMgr->SetLastError(g_ErrBadValue);
1581 g_TwMgr->SetLastError(g_ErrNoValue);
1586 if( _Value!=NULL && strlen(_Value)>0 ) // do not check ReadOnly here.
1588 if( !( m_Type==TW_TYPE_BUTTON || IsCustom() ) ) // || (m_Type>=TW_TYPE_CUSTOM_BASE && m_Type<TW_TYPE_CUSTOM_BASE+(int)g_TwMgr->m_Customs.size()) ) )
1590 if( m_Type==TW_TYPE_CDSTRING || m_Type==TW_TYPE_CDSTDSTRING )
1592 if( m_SetCallback!=NULL )
1594 m_SetCallback(&_Value, m_ClientData);
1595 if( g_TwMgr!=NULL ) // Mgr might have been destroyed by the client inside a callback call
1596 _Bar->NotUpToDate();
1599 else if( m_Type!=TW_TYPE_CDSTDSTRING )
1601 char **StringPtr = (char **)m_Ptr;
1602 if( StringPtr!=NULL && g_TwMgr->m_CopyCDStringToClient!=NULL )
1604 g_TwMgr->m_CopyCDStringToClient(StringPtr, _Value);
1605 _Bar->NotUpToDate();
1610 else if( IsCSStringType(m_Type) )
1612 int n = TW_CSSTRING_SIZE(m_Type);
1615 string str = _Value;
1616 if( (int)str.length()>n-1 )
1618 if( m_SetCallback!=NULL )
1620 m_SetCallback(str.c_str(), m_ClientData);
1621 if( g_TwMgr!=NULL ) // Mgr might have been destroyed by the client inside a callback call
1622 _Bar->NotUpToDate();
1625 else if( m_Ptr!=NULL )
1628 strncpy((char *)m_Ptr, str.c_str(), n-1);
1629 ((char *)m_Ptr)[n-1] = '\0';
1630 _Bar->NotUpToDate();
1638 if( sscanf(_Value, "%lf", &dbl)==1 )
1640 ValueFromDouble(dbl);
1641 if( g_TwMgr!=NULL ) // Mgr might have been destroyed by the client inside a callback call
1642 _Bar->NotUpToDate();
1650 return CTwVar::SetAttrib(_AttribID, _Value, _Bar, _VarParent, _VarIndex);
1654 ERetType CTwVarAtom::GetAttrib(int _AttribID, TwBar *_Bar, CTwVarGroup *_VarParent, int _VarIndex, std::vector<double>& outDoubles, std::ostringstream& outString) const
1664 if( TwGetKeyString(&str, m_KeyIncr[0], m_KeyIncr[1]) )
1668 if( TwGetKeyString(&str, m_KeyDecr[0], m_KeyDecr[1]) )
1672 if( m_Type==TW_TYPE_BOOL8 || m_Type==TW_TYPE_BOOL16 || m_Type==TW_TYPE_BOOL32 || m_Type==TW_TYPE_BOOLCPP )
1674 outString << m_Val.m_Bool.m_TrueString;
1679 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
1683 if( m_Type==TW_TYPE_BOOL8 || m_Type==TW_TYPE_BOOL16 || m_Type==TW_TYPE_BOOL32 || m_Type==TW_TYPE_BOOLCPP )
1685 outString << m_Val.m_Bool.m_FalseString;
1690 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
1696 num = (_AttribID==VA_STEP) ? 2 : ((_AttribID==VA_MAX) ? 1 : 0);
1700 outDoubles.push_back( *((&m_Val.m_Char.m_Min) + num) );
1703 outDoubles.push_back( *((&m_Val.m_Int8.m_Min) + num) );
1706 outDoubles.push_back( *((&m_Val.m_UInt8.m_Min) + num) );
1709 outDoubles.push_back( *((&m_Val.m_Int16.m_Min) + num) );
1712 outDoubles.push_back( *((&m_Val.m_Int32.m_Min) + num) );
1714 case TW_TYPE_UINT16:
1715 outDoubles.push_back( *((&m_Val.m_UInt16.m_Min) + num) );
1717 case TW_TYPE_UINT32:
1718 outDoubles.push_back( *((&m_Val.m_UInt32.m_Min) + num) );
1721 outDoubles.push_back( *((&m_Val.m_Float32.m_Min) + num) );
1723 case TW_TYPE_DOUBLE:
1724 outDoubles.push_back( *((&m_Val.m_Float64.m_Min) + num) );
1727 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
1731 if( m_Type==TW_TYPE_FLOAT )
1733 outDoubles.push_back( m_Val.m_Float32.m_Precision );
1736 else if ( m_Type==TW_TYPE_DOUBLE )
1738 outDoubles.push_back( m_Val.m_Float64.m_Precision );
1743 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
1750 outDoubles.push_back( m_Val.m_Char.m_Hexa );
1753 outDoubles.push_back( m_Val.m_Int8.m_Hexa );
1756 outDoubles.push_back( m_Val.m_Int16.m_Hexa );
1759 outDoubles.push_back( m_Val.m_Int32.m_Hexa );
1762 outDoubles.push_back( m_Val.m_UInt8.m_Hexa );
1764 case TW_TYPE_UINT16:
1765 outDoubles.push_back( m_Val.m_UInt16.m_Hexa );
1767 case TW_TYPE_UINT32:
1768 outDoubles.push_back( m_Val.m_UInt32.m_Hexa );
1771 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
1775 if( IsEnumType(m_Type) )
1777 CTwMgr::CEnum::CEntries::iterator it = g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE].m_Entries.begin();
1778 for( ; it != g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE].m_Entries.end(); ++it )
1780 if( it != g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE].m_Entries.begin() )
1782 outString << it->first << ' ';
1783 if( it->second.find_first_of("{}")==std::string::npos )
1784 outString << '{' << it->second << '}';
1785 else if ( it->second.find_first_of("<>")==std::string::npos )
1786 outString << '<' << it->second << '>';
1787 else if ( it->second.find_first_of("()")==std::string::npos )
1788 outString << '(' << it->second << ')';
1789 else if ( it->second.find_first_of("[]")==std::string::npos )
1790 outString << '[' << it->second << ']';
1792 outString << '{' << it->second << '}'; // should not occured (use braces)
1796 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
1799 if( !( m_Type==TW_TYPE_BUTTON || IsCustom() ) ) // || (m_Type>=TW_TYPE_CUSTOM_BASE && m_Type<TW_TYPE_CUSTOM_BASE+(int)g_TwMgr->m_Customs.size()) ) )
1801 if( m_Type==TW_TYPE_CDSTRING || m_Type==TW_TYPE_CDSTDSTRING || IsCSStringType(m_Type) )
1804 ValueToString(&str);
1810 outDoubles.push_back( ValueToDouble() );
1814 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
1817 return CTwVar::GetAttrib(_AttribID, _Bar, _VarParent, _VarIndex, outDoubles, outString);
1821 // ---------------------------------------------------------------------------
1823 void CTwVarAtom::Increment(int _Step)
1833 v = *((char *)m_Ptr);
1834 else if( m_GetCallback!=NULL )
1835 m_GetCallback(&v, m_ClientData);
1841 *((char *)m_Ptr) = v;
1842 else if( m_SetCallback!=NULL )
1843 m_SetCallback(&v, m_ClientData);
1846 case TW_TYPE_BOOL16:
1850 v = *((short *)m_Ptr);
1851 else if( m_GetCallback!=NULL )
1852 m_GetCallback(&v, m_ClientData);
1858 *((short *)m_Ptr) = v;
1859 else if( m_SetCallback!=NULL )
1860 m_SetCallback(&v, m_ClientData);
1863 case TW_TYPE_BOOL32:
1867 v = *((int *)m_Ptr);
1868 else if( m_GetCallback!=NULL )
1869 m_GetCallback(&v, m_ClientData);
1875 *((int *)m_Ptr) = v;
1876 else if( m_SetCallback!=NULL )
1877 m_SetCallback(&v, m_ClientData);
1880 case TW_TYPE_BOOLCPP:
1884 v = *((bool *)m_Ptr);
1885 else if( m_GetCallback!=NULL )
1886 m_GetCallback(&v, m_ClientData);
1892 *((bool *)m_Ptr) = v;
1893 else if( m_SetCallback!=NULL )
1894 m_SetCallback(&v, m_ClientData);
1899 unsigned char v = 0;
1901 v = *((unsigned char *)m_Ptr);
1902 else if( m_GetCallback!=NULL )
1903 m_GetCallback(&v, m_ClientData);
1904 int iv = _Step*(int)m_Val.m_Char.m_Step + (int)v;
1905 if( iv<m_Val.m_Char.m_Min )
1906 iv = m_Val.m_Char.m_Min;
1907 if( iv>m_Val.m_Char.m_Max )
1908 iv = m_Val.m_Char.m_Max;
1913 v = (unsigned char)iv;
1915 *((unsigned char *)m_Ptr) = v;
1916 else if( m_SetCallback!=NULL )
1917 m_SetCallback(&v, m_ClientData);
1924 v = *((signed char *)m_Ptr);
1925 else if( m_GetCallback!=NULL )
1926 m_GetCallback(&v, m_ClientData);
1927 int iv = _Step*(int)m_Val.m_Int8.m_Step + (int)v;
1928 if( iv<m_Val.m_Int8.m_Min )
1929 iv = m_Val.m_Int8.m_Min;
1930 if( iv>m_Val.m_Int8.m_Max )
1931 iv = m_Val.m_Int8.m_Max;
1932 v = (signed char)iv;
1934 *((signed char *)m_Ptr) = v;
1935 else if( m_SetCallback!=NULL )
1936 m_SetCallback(&v, m_ClientData);
1941 unsigned char v = 0;
1943 v = *((unsigned char *)m_Ptr);
1944 else if( m_GetCallback!=NULL )
1945 m_GetCallback(&v, m_ClientData);
1946 int iv = _Step*(int)m_Val.m_UInt8.m_Step + (int)v;
1947 if( iv<m_Val.m_UInt8.m_Min )
1948 iv = m_Val.m_UInt8.m_Min;
1949 if( iv>m_Val.m_UInt8.m_Max )
1950 iv = m_Val.m_UInt8.m_Max;
1955 v = (unsigned char)iv;
1957 *((unsigned char *)m_Ptr) = v;
1958 else if( m_SetCallback!=NULL )
1959 m_SetCallback(&v, m_ClientData);
1966 v = *((short *)m_Ptr);
1967 else if( m_GetCallback!=NULL )
1968 m_GetCallback(&v, m_ClientData);
1969 int iv = _Step*(int)m_Val.m_Int16.m_Step + (int)v;
1970 if( iv<m_Val.m_Int16.m_Min )
1971 iv = m_Val.m_Int16.m_Min;
1972 if( iv>m_Val.m_Int16.m_Max )
1973 iv = m_Val.m_Int16.m_Max;
1976 *((short *)m_Ptr) = v;
1977 else if( m_SetCallback!=NULL )
1978 m_SetCallback(&v, m_ClientData);
1981 case TW_TYPE_UINT16:
1983 unsigned short v = 0;
1985 v = *((unsigned short *)m_Ptr);
1986 else if( m_GetCallback!=NULL )
1987 m_GetCallback(&v, m_ClientData);
1988 int iv = _Step*(int)m_Val.m_UInt16.m_Step + (int)v;
1989 if( iv<m_Val.m_UInt16.m_Min )
1990 iv = m_Val.m_UInt16.m_Min;
1991 if( iv>m_Val.m_UInt16.m_Max )
1992 iv = m_Val.m_UInt16.m_Max;
1995 else if( iv>0xffff )
1997 v = (unsigned short)iv;
1999 *((unsigned short *)m_Ptr) = v;
2000 else if( m_SetCallback!=NULL )
2001 m_SetCallback(&v, m_ClientData);
2008 v = *((int *)m_Ptr);
2009 else if( m_GetCallback!=NULL )
2010 m_GetCallback(&v, m_ClientData);
2011 double dv = (double)_Step*(double)m_Val.m_Int32.m_Step + (double)v;
2012 if( dv>(double)0x7fffffff )
2014 else if( dv<(double)(-0x7fffffff-1) )
2017 v = _Step*m_Val.m_Int32.m_Step + v;
2018 if( v<m_Val.m_Int32.m_Min )
2019 v = m_Val.m_Int32.m_Min;
2020 if( v>m_Val.m_Int32.m_Max )
2021 v = m_Val.m_Int32.m_Max;
2023 *((int *)m_Ptr) = v;
2024 else if( m_SetCallback!=NULL )
2025 m_SetCallback(&v, m_ClientData);
2028 case TW_TYPE_UINT32:
2032 v = *((unsigned int *)m_Ptr);
2033 else if( m_GetCallback!=NULL )
2034 m_GetCallback(&v, m_ClientData);
2035 double dv = (double)_Step*(double)m_Val.m_UInt32.m_Step + (double)v;
2036 if( dv>(double)0xffffffff )
2041 v = _Step*m_Val.m_UInt32.m_Step + v;
2042 if( v<m_Val.m_UInt32.m_Min )
2043 v = m_Val.m_UInt32.m_Min;
2044 if( v>m_Val.m_UInt32.m_Max )
2045 v = m_Val.m_UInt32.m_Max;
2047 *((unsigned int *)m_Ptr) = v;
2048 else if( m_SetCallback!=NULL )
2049 m_SetCallback(&v, m_ClientData);
2056 v = *((float *)m_Ptr);
2057 else if( m_GetCallback!=NULL )
2058 m_GetCallback(&v, m_ClientData);
2059 v += _Step*m_Val.m_Float32.m_Step;
2060 if( v<m_Val.m_Float32.m_Min )
2061 v = m_Val.m_Float32.m_Min;
2062 if( v>m_Val.m_Float32.m_Max )
2063 v = m_Val.m_Float32.m_Max;
2065 *((float *)m_Ptr) = v;
2066 else if( m_SetCallback!=NULL )
2067 m_SetCallback(&v, m_ClientData);
2070 case TW_TYPE_DOUBLE:
2074 v = *((double *)m_Ptr);
2075 else if( m_GetCallback!=NULL )
2076 m_GetCallback(&v, m_ClientData);
2077 v += _Step*m_Val.m_Float64.m_Step;
2078 if( v<m_Val.m_Float64.m_Min )
2079 v = m_Val.m_Float64.m_Min;
2080 if( v>m_Val.m_Float64.m_Max )
2081 v = m_Val.m_Float64.m_Max;
2083 *((double *)m_Ptr) = v;
2084 else if( m_SetCallback!=NULL )
2085 m_SetCallback(&v, m_ClientData);
2091 assert(_Step==1 || _Step==-1);
2092 unsigned char v = 0;
2094 v = *((unsigned char *)m_Ptr);
2095 else if( m_GetCallback!=NULL )
2096 m_GetCallback(&v, m_ClientData);
2097 if( m_Val.m_Enum.m_Entries!=NULL )
2099 UVal::CEnumVal::CEntries::iterator It = m_Val.m_Enum.m_Entries->find(v);
2100 if( It==m_Val.m_Enum.m_Entries->end() )
2101 It = m_Val.m_Enum.m_Entries->begin();
2105 if( It==m_Val.m_Enum.m_Entries->end() )
2106 It = m_Val.m_Enum.m_Entries->begin();
2108 else if( _Step==-1 )
2110 if( It==m_Val.m_Enum.m_Entries->begin() )
2111 It = m_Val.m_Enum.m_Entries->end();
2112 if( It!=m_Val.m_Enum.m_Entries->begin() )
2115 if( It != m_Val.m_Enum.m_Entries->end() )
2117 v = (unsigned char)(It->first);
2119 *((unsigned char *)m_Ptr) = v;
2120 else if( m_SetCallback!=NULL )
2121 m_SetCallback(&v, m_ClientData);
2126 case TW_TYPE_ENUM16:
2128 assert(_Step==1 || _Step==-1);
2129 unsigned short v = 0;
2131 v = *((unsigned short *)m_Ptr);
2132 else if( m_GetCallback!=NULL )
2133 m_GetCallback(&v, m_ClientData);
2134 if( m_Val.m_Enum.m_Entries!=NULL )
2136 UVal::CEnumVal::CEntries::iterator It = m_Val.m_Enum.m_Entries->find(v);
2137 if( It==m_Val.m_Enum.m_Entries->end() )
2138 It = m_Val.m_Enum.m_Entries->begin();
2142 if( It==m_Val.m_Enum.m_Entries->end() )
2143 It = m_Val.m_Enum.m_Entries->begin();
2145 else if( _Step==-1 )
2147 if( It==m_Val.m_Enum.m_Entries->begin() )
2148 It = m_Val.m_Enum.m_Entries->end();
2149 if( It!=m_Val.m_Enum.m_Entries->begin() )
2152 if( It != m_Val.m_Enum.m_Entries->end() )
2154 v = (unsigned short)(It->first);
2156 *((unsigned short *)m_Ptr) = v;
2157 else if( m_SetCallback!=NULL )
2158 m_SetCallback(&v, m_ClientData);
2163 case TW_TYPE_ENUM32:
2165 assert(_Step==1 || _Step==-1);
2168 v = *((unsigned int *)m_Ptr);
2169 else if( m_GetCallback!=NULL )
2170 m_GetCallback(&v, m_ClientData);
2171 if( m_Val.m_Enum.m_Entries!=NULL )
2173 UVal::CEnumVal::CEntries::iterator It = m_Val.m_Enum.m_Entries->find(v);
2174 if( It==m_Val.m_Enum.m_Entries->end() )
2175 It = m_Val.m_Enum.m_Entries->begin();
2179 if( It==m_Val.m_Enum.m_Entries->end() )
2180 It = m_Val.m_Enum.m_Entries->begin();
2182 else if( _Step==-1 )
2184 if( It==m_Val.m_Enum.m_Entries->begin() )
2185 It = m_Val.m_Enum.m_Entries->end();
2186 if( It!=m_Val.m_Enum.m_Entries->begin() )
2189 if( It!=m_Val.m_Enum.m_Entries->end() )
2191 v = (unsigned int)(It->first);
2193 *((unsigned int *)m_Ptr) = v;
2194 else if( m_SetCallback!=NULL )
2195 m_SetCallback(&v, m_ClientData);
2202 if( m_Type==TW_TYPE_BUTTON )
2204 if( m_Val.m_Button.m_Callback!=NULL )
2206 m_Val.m_Button.m_Callback(m_ClientData);
2207 if( g_TwMgr==NULL ) // Mgr might have been destroyed by the client inside a callback call
2211 else if( IsEnumType(m_Type) )
2213 assert(_Step==1 || _Step==-1);
2216 v = *((unsigned int *)m_Ptr);
2217 else if( m_GetCallback!=NULL )
2218 m_GetCallback(&v, m_ClientData);
2219 CTwMgr::CEnum& e = g_TwMgr->m_Enums[m_Type-TW_TYPE_ENUM_BASE];
2220 CTwMgr::CEnum::CEntries::iterator It = e.m_Entries.find(v);
2221 if( It==e.m_Entries.end() )
2222 It = e.m_Entries.begin();
2226 if( It==e.m_Entries.end() )
2227 It = e.m_Entries.begin();
2229 else if( _Step==-1 )
2231 if( It==e.m_Entries.begin() )
2232 It = e.m_Entries.end();
2233 if( It!=e.m_Entries.begin() )
2236 if( It!=e.m_Entries.end() )
2238 v = (unsigned int)(It->first);
2240 *((unsigned int *)m_Ptr) = v;
2241 else if( m_SetCallback!=NULL )
2242 m_SetCallback(&v, m_ClientData);
2246 fprintf(stderr, "CTwVarAtom::Increment : unknown or unimplemented type\n");
2250 // ---------------------------------------------------------------------------
2252 void CTwVarAtom::SetDefaults()
2257 case TW_TYPE_BOOL16:
2258 case TW_TYPE_BOOL32:
2259 case TW_TYPE_BOOLCPP:
2263 m_Val.m_Char.m_Max = 0xff;
2264 m_Val.m_Char.m_Min = 0;
2265 m_Val.m_Char.m_Step = 1;
2266 m_Val.m_Char.m_Precision = -1;
2267 m_Val.m_Char.m_Hexa = false;
2270 m_Val.m_Int8.m_Max = 0x7f;
2271 m_Val.m_Int8.m_Min = -m_Val.m_Int8.m_Max-1;
2272 m_Val.m_Int8.m_Step = 1;
2273 m_Val.m_Int8.m_Precision = -1;
2274 m_Val.m_Int8.m_Hexa = false;
2277 m_Val.m_UInt8.m_Max = 0xff;
2278 m_Val.m_UInt8.m_Min = 0;
2279 m_Val.m_UInt8.m_Step = 1;
2280 m_Val.m_UInt8.m_Precision = -1;
2281 m_Val.m_UInt8.m_Hexa = false;
2284 m_Val.m_Int16.m_Max = 0x7fff;
2285 m_Val.m_Int16.m_Min = -m_Val.m_Int16.m_Max-1;
2286 m_Val.m_Int16.m_Step = 1;
2287 m_Val.m_Int16.m_Precision = -1;
2288 m_Val.m_Int16.m_Hexa = false;
2290 case TW_TYPE_UINT16:
2291 m_Val.m_UInt16.m_Max = 0xffff;
2292 m_Val.m_UInt16.m_Min = 0;
2293 m_Val.m_UInt16.m_Step = 1;
2294 m_Val.m_UInt16.m_Precision = -1;
2295 m_Val.m_UInt16.m_Hexa = false;
2298 m_Val.m_Int32.m_Max = 0x7fffffff;
2299 m_Val.m_Int32.m_Min = -m_Val.m_Int32.m_Max-1;
2300 m_Val.m_Int32.m_Step = 1;
2301 m_Val.m_Int32.m_Precision = -1;
2302 m_Val.m_Int32.m_Hexa = false;
2304 case TW_TYPE_UINT32:
2305 m_Val.m_UInt32.m_Max = 0xffffffff;
2306 m_Val.m_UInt32.m_Min = 0;
2307 m_Val.m_UInt32.m_Step = 1;
2308 m_Val.m_UInt32.m_Precision = -1;
2309 m_Val.m_UInt32.m_Hexa = false;
2312 m_Val.m_Float32.m_Max = FLOAT_MAX;
2313 m_Val.m_Float32.m_Min = -FLOAT_MAX;
2314 m_Val.m_Float32.m_Step = 1;
2315 m_Val.m_Float32.m_Precision = -1;
2316 m_Val.m_Float32.m_Hexa = false;
2318 case TW_TYPE_DOUBLE:
2319 m_Val.m_Float64.m_Max = DOUBLE_MAX;
2320 m_Val.m_Float64.m_Min = -DOUBLE_MAX;
2321 m_Val.m_Float64.m_Step = 1;
2322 m_Val.m_Float64.m_Precision = -1;
2323 m_Val.m_Float64.m_Hexa = false;
2325 case TW_TYPE_CDSTRING:
2326 case TW_TYPE_STDSTRING:
2331 case TW_TYPE_ENUM16:
2332 case TW_TYPE_ENUM32:
2341 if( m_Type==TW_TYPE_BUTTON
2342 || IsEnumType(m_Type) // (m_Type>=TW_TYPE_ENUM_BASE && m_Type<TW_TYPE_ENUM_BASE+(int)g_TwMgr->m_Enums.size())
2343 || IsCSStringType(m_Type) // (m_Type>=TW_TYPE_CSSTRING_BASE && m_Type<=TW_TYPE_CSSTRING_MAX)
2344 || m_Type==TW_TYPE_CDSTDSTRING
2345 || IsCustom() ) // (m_Type>=TW_TYPE_CUSTOM_BASE && m_Type<TW_TYPE_CUSTOM_BASE+(int)g_TwMgr->m_Customs.size()) )
2349 // ---------------------------------------------------------------------------
2352 int CTwVarAtom::DefineEnum(const TwEnumVal *_EnumValues, unsigned int _NbValues)
2354 assert(_EnumValues!=NULL);
2355 if( m_Type!=TW_TYPE_ENUM8 && m_Type!=TW_TYPE_ENUM16 && m_Type!=TW_TYPE_ENUM32 )
2357 g_TwMgr->SetLastError(g_ErrNotEnum);
2360 if( m_Val.m_Enum.m_Entries==NULL )
2361 m_Val.m_Enum.m_Entries = new UVal::CEnumVal::CEntries;
2362 for(unsigned int i=0; i<_NbValues; ++i)
2364 UVal::CEnumVal::CEntries::value_type Entry(_EnumValues[i].Value, (_EnumValues[i].Label!=NULL)?_EnumValues[i].Label:"");
2365 pair<UVal::CEnumVal::CEntries::iterator, bool> Result = m_Val.m_Enum.m_Entries->insert(Entry);
2366 if( !Result.second )
2367 (Result.first)->second = Entry.second;
2373 // ---------------------------------------------------------------------------
2375 enum EVarGroupAttribs
2377 VG_OPEN = V_ENDTAG+1, // for backward compatibility
2378 VG_CLOSE, // for backward compatibility
2380 VG_TYPEID, // used internally for structs
2381 VG_VALPTR, // used internally for structs
2382 VG_ALPHA, // for backward compatibility
2383 VG_NOALPHA, // for backward compatibility
2384 VG_COLORALPHA, // tw_type_color* only
2385 VG_HLS, // for backward compatibility
2386 VG_RGB, // for backward compatibility
2387 VG_COLORMODE, // tw_type_color* only
2388 VG_COLORORDER, // tw_type_color* only
2389 VG_ARROW, // tw_type_quat* only
2390 VG_ARROWCOLOR, // tw_type_quat* only
2391 VG_AXISX, // tw_type_quat* only
2392 VG_AXISY, // tw_type_quat* only
2393 VG_AXISZ, // tw_type_quat* only
2394 VG_SHOWVAL // tw_type_quat* only
2397 int CTwVarGroup::HasAttrib(const char *_Attrib, bool *_HasValue) const
2400 if( _stricmp(_Attrib, "open")==0 ) // for backward compatibility
2402 else if( _stricmp(_Attrib, "close")==0 ) // for backward compatibility
2404 else if( _stricmp(_Attrib, "opened")==0 )
2409 else if( _stricmp(_Attrib, "typeid")==0 )
2414 else if( _stricmp(_Attrib, "valptr")==0 )
2419 else if( _stricmp(_Attrib, "alpha")==0 ) // for backward compatibility
2421 else if( _stricmp(_Attrib, "noalpha")==0 ) // for backward compatibility
2423 else if( _stricmp(_Attrib, "coloralpha")==0 )
2426 return VG_COLORALPHA;
2428 else if( _stricmp(_Attrib, "hls")==0 ) // for backward compatibility
2430 else if( _stricmp(_Attrib, "rgb")==0 ) // for backward compatibility
2432 else if( _stricmp(_Attrib, "colormode")==0 )
2435 return VG_COLORMODE;
2437 else if( _stricmp(_Attrib, "colororder")==0 )
2440 return VG_COLORORDER;
2442 else if( _stricmp(_Attrib, "arrow")==0 )
2447 else if( _stricmp(_Attrib, "arrowcolor")==0 )
2450 return VG_ARROWCOLOR;
2452 else if( _stricmp(_Attrib, "axisx")==0 )
2457 else if( _stricmp(_Attrib, "axisy")==0 )
2462 else if( _stricmp(_Attrib, "axisz")==0 )
2467 else if( _stricmp(_Attrib, "showval")==0 )
2473 return CTwVar::HasAttrib(_Attrib, _HasValue);
2476 int CTwVarGroup::SetAttrib(int _AttribID, const char *_Value, TwBar *_Bar, struct CTwVarGroup *_VarParent, int _VarIndex)
2480 case VG_OPEN: // for backward compatibility
2484 _Bar->NotUpToDate();
2487 case VG_CLOSE: // for backward compatibility
2491 _Bar->NotUpToDate();
2495 if( _Value!=NULL && strlen(_Value)>0 )
2497 if( _stricmp(_Value, "true")==0 || _stricmp(_Value, "1")==0 )
2502 _Bar->NotUpToDate();
2506 else if( _stricmp(_Value, "false")==0 || _stricmp(_Value, "0")==0 )
2511 _Bar->NotUpToDate();
2517 g_TwMgr->SetLastError(g_ErrBadValue);
2523 g_TwMgr->SetLastError(g_ErrNoValue);
2528 int type = TW_TYPE_UNDEF;
2529 if( _Value!=NULL && sscanf(_Value, "%d", &type)==1 )
2531 int idx = type - TW_TYPE_STRUCT_BASE;
2532 if( idx>=0 && idx<(int)g_TwMgr->m_Structs.size() )
2534 m_SummaryCallback = g_TwMgr->m_Structs[idx].m_SummaryCallback;
2535 m_SummaryClientData = g_TwMgr->m_Structs[idx].m_SummaryClientData;
2536 m_StructType = (TwType)type;
2544 void *structValuePtr = NULL;
2545 if( _Value!=NULL && sscanf(_Value, "%p", &structValuePtr)==1 )
2547 m_StructValuePtr = structValuePtr;
2548 m_ColorPtr = &(_Bar->m_ColStructText);
2553 case VG_ALPHA: // for backward compatibility
2554 if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color?
2555 if( static_cast<CColorExt *>(m_StructValuePtr)->m_CanHaveAlpha )
2557 static_cast<CColorExt *>(m_StructValuePtr)->m_HasAlpha = true;
2558 _Bar->NotUpToDate();
2562 case VG_NOALPHA: // for backward compatibility
2563 if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color?
2565 static_cast<CColorExt *>(m_StructValuePtr)->m_HasAlpha = false;
2566 _Bar->NotUpToDate();
2572 if( _Value!=NULL && strlen(_Value)>0 )
2574 if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color?
2576 if( _stricmp(_Value, "true")==0 || _stricmp(_Value, "1")==0 )
2578 if( static_cast<CColorExt *>(m_StructValuePtr)->m_CanHaveAlpha )
2580 if( !static_cast<CColorExt *>(m_StructValuePtr)->m_HasAlpha )
2582 static_cast<CColorExt *>(m_StructValuePtr)->m_HasAlpha = true;
2583 _Bar->NotUpToDate();
2588 else if( _stricmp(_Value, "false")==0 || _stricmp(_Value, "0")==0 )
2590 if( static_cast<CColorExt *>(m_StructValuePtr)->m_HasAlpha )
2592 static_cast<CColorExt *>(m_StructValuePtr)->m_HasAlpha = false;
2593 _Bar->NotUpToDate();
2600 case VG_HLS: // for backward compatibility
2601 if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color?
2603 static_cast<CColorExt *>(m_StructValuePtr)->m_HLS = true;
2604 _Bar->NotUpToDate();
2609 case VG_RGB: // for backward compatibility
2610 if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color?
2612 static_cast<CColorExt *>(m_StructValuePtr)->m_HLS = false;
2613 _Bar->NotUpToDate();
2619 if( _Value!=NULL && strlen(_Value)>0 )
2621 if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color?
2623 if( _stricmp(_Value, "hls")==0 )
2625 if( !static_cast<CColorExt *>(m_StructValuePtr)->m_HLS )
2627 static_cast<CColorExt *>(m_StructValuePtr)->m_HLS = true;
2628 _Bar->NotUpToDate();
2632 else if( _stricmp(_Value, "rgb")==0 )
2634 if( static_cast<CColorExt *>(m_StructValuePtr)->m_HLS )
2636 static_cast<CColorExt *>(m_StructValuePtr)->m_HLS = false;
2637 _Bar->NotUpToDate();
2645 if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color?
2649 if( _stricmp(_Value, "rgba")==0 )
2650 static_cast<CColorExt *>(m_StructValuePtr)->m_OGL = true;
2651 else if( _stricmp(_Value, "argb")==0 )
2652 static_cast<CColorExt *>(m_StructValuePtr)->m_OGL = false;
2662 if( m_SummaryCallback==CQuaternionExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_quat?
2666 double *dir = static_cast<CQuaternionExt *>(m_StructValuePtr)->m_Dir;
2668 if( sscanf(_Value, "%lf %lf %lf", &x, &y, &z)==3 )
2674 else if( _stricmp(_Value, "off")==0 || _stricmp(_Value, "0")==0 )
2675 dir[0] = dir[1] = dir[2] = 0;
2685 if( m_SummaryCallback==CQuaternionExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_quat?
2690 if( sscanf(_Value, "%d %d %d", &r, &g, &b)==3 )
2691 static_cast<CQuaternionExt *>(m_StructValuePtr)->m_DirColor = Color32FromARGBi(255, r, g, b);
2703 if( m_SummaryCallback==CQuaternionExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_quat?
2707 float x = 0, y = 0, z = 0;
2708 if( _stricmp(_Value, "x")==0 || _stricmp(_Value, "+x")==0 )
2710 else if( _stricmp(_Value, "-x")==0 )
2712 else if( _stricmp(_Value, "y")==0 || _stricmp(_Value, "+y")==0 )
2714 else if( _stricmp(_Value, "-y")==0 )
2716 else if( _stricmp(_Value, "z")==0 || _stricmp(_Value, "+z")==0 )
2718 else if( _stricmp(_Value, "-z")==0 )
2722 int i = (_AttribID==VG_AXISX) ? 0 : ((_AttribID==VG_AXISY) ? 1 : 2);
2723 static_cast<CQuaternionExt *>(m_StructValuePtr)->m_Permute[i][0] = x;
2724 static_cast<CQuaternionExt *>(m_StructValuePtr)->m_Permute[i][1] = y;
2725 static_cast<CQuaternionExt *>(m_StructValuePtr)->m_Permute[i][2] = z;
2733 if( m_SummaryCallback==CQuaternionExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_quat?
2737 if( _stricmp(_Value, "true")==0 || _stricmp(_Value, "on")==0 || _stricmp(_Value, "1")==0 )
2739 static_cast<CQuaternionExt *>(m_StructValuePtr)->m_ShowVal = true;
2740 _Bar->NotUpToDate();
2743 else if( _stricmp(_Value, "false")==0 || _stricmp(_Value, "off")==0 || _stricmp(_Value, "0")==0 )
2745 static_cast<CQuaternionExt *>(m_StructValuePtr)->m_ShowVal = false;
2746 _Bar->NotUpToDate();
2755 return CTwVar::SetAttrib(_AttribID, _Value, _Bar, _VarParent, _VarIndex);
2759 ERetType CTwVarGroup::GetAttrib(int _AttribID, TwBar *_Bar, struct CTwVarGroup *_VarParent, int _VarIndex, std::vector<double>& outDoubles, std::ostringstream& outString) const
2767 outDoubles.push_back( m_Open );
2770 if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color?
2772 outDoubles.push_back( static_cast<CColorExt *>(m_StructValuePtr)->m_HasAlpha );
2775 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
2778 if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color?
2780 if( static_cast<CColorExt *>(m_StructValuePtr)->m_HLS )
2786 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
2789 if( m_SummaryCallback==CColorExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_color?
2791 if( static_cast<CColorExt *>(m_StructValuePtr)->m_OGL )
2792 outString << "rgba";
2794 outString << "argb";
2797 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
2800 if( m_SummaryCallback==CQuaternionExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_quat?
2802 double *dir = static_cast<CQuaternionExt *>(m_StructValuePtr)->m_Dir;
2803 outDoubles.push_back(dir[0]);
2804 outDoubles.push_back(dir[1]);
2805 outDoubles.push_back(dir[2]);
2808 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
2811 if( m_SummaryCallback==CQuaternionExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_quat?
2815 Color32ToARGBi(static_cast<CQuaternionExt *>(m_StructValuePtr)->m_DirColor, &a, &r, &g, &b);
2816 outDoubles.push_back(r);
2817 outDoubles.push_back(g);
2818 outDoubles.push_back(b);
2821 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
2826 if( m_SummaryCallback==CQuaternionExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_quat?
2828 int i = (_AttribID==VG_AXISX) ? 0 : ((_AttribID==VG_AXISY) ? 1 : 2);
2829 float x = static_cast<CQuaternionExt *>(m_StructValuePtr)->m_Permute[i][0];
2830 float y = static_cast<CQuaternionExt *>(m_StructValuePtr)->m_Permute[i][1];
2831 float z = static_cast<CQuaternionExt *>(m_StructValuePtr)->m_Permute[i][2];
2845 outString << "0"; // should not happened
2848 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
2851 if( m_SummaryCallback==CQuaternionExt::SummaryCB && m_StructValuePtr!=NULL ) // is tw_type_quat?
2853 outDoubles.push_back( static_cast<CQuaternionExt *>(m_StructValuePtr)->m_ShowVal );
2856 g_TwMgr->SetLastError(g_ErrInvalidAttrib);
2859 return CTwVar::GetAttrib(_AttribID, _Bar, _VarParent, _VarIndex, outDoubles, outString);
2863 // ---------------------------------------------------------------------------
2865 const CTwVar *CTwVarGroup::Find(const char *_Name, CTwVarGroup **_Parent, int *_Index) const
2867 if( strcmp(_Name, m_Name.c_str())==0 )
2878 for( size_t i=0; i<m_Vars.size(); ++ i )
2879 if( m_Vars[i]!=NULL )
2881 v = m_Vars[i]->Find(_Name, _Parent, _Index);
2884 if( _Parent!=NULL && *_Parent==NULL )
2886 *_Parent = const_cast<CTwVarGroup *>(this);
2897 // ---------------------------------------------------------------------------
2899 size_t CTwVar::GetDataSize(TwType _Type)
2903 case TW_TYPE_BOOLCPP:
2904 return sizeof(bool);
2909 //case TW_TYPE_ENUM8:
2911 case TW_TYPE_BOOL16:
2913 case TW_TYPE_UINT16:
2914 //case TW_TYPE_ENUM16:
2916 case TW_TYPE_BOOL32:
2918 case TW_TYPE_UINT32:
2920 //case TW_TYPE_ENUM32:
2922 case TW_TYPE_DOUBLE:
2924 case TW_TYPE_CDSTRING:
2925 return sizeof(char *);
2926 case TW_TYPE_STDSTRING:
2927 return (g_TwMgr!=0) ? g_TwMgr->m_ClientStdStringStructSize : sizeof(std::string);
2929 if( g_TwMgr && _Type>=TW_TYPE_STRUCT_BASE && _Type<TW_TYPE_STRUCT_BASE+(int)g_TwMgr->m_Structs.size() )
2931 const CTwMgr::CStruct& s = g_TwMgr->m_Structs[_Type-TW_TYPE_STRUCT_BASE];
2935 for( size_t i=0; i<s.m_Members.size(); ++i )
2936 size += s.m_Members[i].m_Size;
2940 else if( g_TwMgr && IsEnumType(_Type) )
2942 else if( IsCSStringType(_Type) )
2943 return TW_CSSTRING_SIZE(_Type);
2944 else if( _Type==TW_TYPE_CDSTDSTRING )
2945 return (g_TwMgr!=0) ? g_TwMgr->m_ClientStdStringStructSize : sizeof(std::string);
2946 else // includes TW_TYPE_BUTTON
2951 // ---------------------------------------------------------------------------
2953 CTwBar::CTwBar(const char *_Name)
2955 assert(g_TwMgr!=NULL && g_TwMgr->m_Graph!=NULL);
2959 m_VarRoot.m_IsRoot = true;
2960 m_VarRoot.m_Open = true;
2961 m_VarRoot.m_SummaryCallback = NULL;
2962 m_VarRoot.m_SummaryClientData = NULL;
2963 m_VarRoot.m_StructValuePtr = NULL;
2966 int n = (int)g_TwMgr->m_Bars.size();
2972 if( g_TwMgr->m_UseOldColorScheme )
2974 ColorHLSToRGBi(g_TwMgr->m_BarInitColorHue%256, 180, 200, &cr, &cg, &cb);
2975 m_Color = Color32FromARGBi(0xf0, cr, cg, cb);
2980 ColorHLSToRGBi(g_TwMgr->m_BarInitColorHue%256, 80, 200, &cr, &cg, &cb);
2981 m_Color = Color32FromARGBi(64, cr, cg, cb);
2984 g_TwMgr->m_BarInitColorHue -= 16;
2985 if( g_TwMgr->m_BarInitColorHue<0 )
2986 g_TwMgr->m_BarInitColorHue += 256;
2987 m_Font = g_TwMgr->m_CurrentFont;
2988 //m_Font = g_DefaultNormalFont;
2989 //m_Font = g_DefaultSmallFont;
2990 //m_Font = g_DefaultLargeFont;
2993 //#pragma warning "lineSep WIP"
2995 m_ValuesWidth = 10*(m_Font->m_CharHeight/2); // about 10 characters
2997 m_NbDisplayedLines = 0;
2999 m_LastUpdateTime = 0;
3006 m_DrawHandles = false;
3007 m_DrawIncrDecrBtn = false;
3008 m_DrawRotoBtn = false;
3009 m_DrawClickBtn = false;
3010 m_DrawListBtn = false;
3011 m_DrawBoolBtn = false;
3012 m_MouseDrag = false;
3013 m_MouseDragVar = false;
3014 m_MouseDragTitle = false;
3015 m_MouseDragScroll = false;
3016 m_MouseDragResizeUR = false;
3017 m_MouseDragResizeUL = false;
3018 m_MouseDragResizeLR = false;
3019 m_MouseDragResizeLL = false;
3020 m_MouseDragValWidth = false;
3023 m_ValuesWidthRatio = 0;
3024 m_VarHasBeenIncr = true;
3026 m_HighlightedLine = -1;
3027 m_HighlightedLinePrev = -1;
3028 m_HighlightedLineLastValid = -1;
3029 m_HighlightIncrBtn = false;
3030 m_HighlightDecrBtn = false;
3031 m_HighlightRotoBtn = false;
3032 m_HighlightClickBtn = false;
3033 m_HighlightClickBtnAuto = 0;
3034 m_HighlightListBtn = false;
3035 m_HighlightBoolBtn = false;
3036 m_HighlightTitle = false;
3037 m_HighlightScroll = false;
3038 m_HighlightUpScroll = false;
3039 m_HighlightDnScroll = false;
3040 m_HighlightMinimize = false;
3041 m_HighlightFont = false;
3042 m_HighlightValWidth = false;
3043 m_HighlightLabelsHeader = false;
3044 m_HighlightValuesHeader = false;
3045 m_ButtonAlign = g_TwMgr->m_ButtonAlign;
3047 m_IsMinimized = false;
3051 m_HighlightMaximize = false;
3052 m_IsHelpBar = false;
3053 m_IsPopupList = false;
3054 m_VarEnumLinkedToPopupList = NULL;
3055 m_BarLinkedToPopupList = NULL;
3059 m_Iconifiable = true;
3060 m_Contained = g_TwMgr->m_Contained;
3062 m_TitleTextObj = g_TwMgr->m_Graph->NewTextObj();
3063 m_LabelsTextObj = g_TwMgr->m_Graph->NewTextObj();
3064 m_ValuesTextObj = g_TwMgr->m_Graph->NewTextObj();
3065 m_ShortcutTextObj = g_TwMgr->m_Graph->NewTextObj();
3066 m_HeadersTextObj = g_TwMgr->m_Graph->NewTextObj();
3067 m_ShortcutLine = -1;
3069 m_RotoMinRadius = 24;
3070 m_RotoNbSubdiv = 256; // number of steps for one turn
3072 m_CustomActiveStructProxy = NULL;
3078 // ---------------------------------------------------------------------------
3083 g_TwMgr->Maximize(this);
3084 if( m_TitleTextObj )
3085 g_TwMgr->m_Graph->DeleteTextObj(m_TitleTextObj);
3086 if( m_LabelsTextObj )
3087 g_TwMgr->m_Graph->DeleteTextObj(m_LabelsTextObj);
3088 if( m_ValuesTextObj )
3089 g_TwMgr->m_Graph->DeleteTextObj(m_ValuesTextObj);
3090 if( m_ShortcutTextObj )
3091 g_TwMgr->m_Graph->DeleteTextObj(m_ShortcutTextObj);
3092 if( m_HeadersTextObj )
3093 g_TwMgr->m_Graph->DeleteTextObj(m_HeadersTextObj);
3096 // ---------------------------------------------------------------------------
3098 const CTwVar *CTwBar::Find(const char *_Name, CTwVarGroup **_Parent, int *_Index) const
3100 return m_VarRoot.Find(_Name, _Parent, _Index);
3103 CTwVar *CTwBar::Find(const char *_Name, CTwVarGroup **_Parent, int *_Index)
3105 return const_cast<CTwVar *>(const_cast<const CTwBar *>(this)->Find(_Name, _Parent, _Index));
3108 // ---------------------------------------------------------------------------
3117 BAR_SHOW, // deprecated, used BAR_VISIBLE instead
3118 BAR_HIDE, // deprecated, used BAR_VISIBLE instead
3119 BAR_ICONIFY, // deprecated, used BAR_ICONIFIED instead
3142 int CTwBar::HasAttrib(const char *_Attrib, bool *_HasValue) const
3145 if( _stricmp(_Attrib, "label")==0 )
3147 else if( _stricmp(_Attrib, "help")==0 )
3149 else if( _stricmp(_Attrib, "color")==0 )
3151 else if( _stricmp(_Attrib, "alpha")==0 )
3153 else if( _stricmp(_Attrib, "text")==0 )
3155 else if( _stricmp(_Attrib, "size")==0 )
3157 else if( _stricmp(_Attrib, "position")==0 )
3158 return BAR_POSITION;
3159 else if( _stricmp(_Attrib, "refresh")==0 )
3161 else if( _stricmp(_Attrib, "fontsize")==0 )
3162 return BAR_FONT_SIZE;
3163 else if( _stricmp(_Attrib, "fontstyle")==0 )
3164 return BAR_FONT_STYLE;
3165 else if( _stricmp(_Attrib, "valueswidth")==0 )
3166 return BAR_VALUES_WIDTH;
3167 else if( _stricmp(_Attrib, "iconpos")==0 )
3168 return BAR_ICON_POS;
3169 else if( _stricmp(_Attrib, "iconalign")==0 )
3170 return BAR_ICON_ALIGN;
3171 else if( _stricmp(_Attrib, "iconmargin")==0 )
3172 return BAR_ICON_MARGIN;
3173 else if( _stricmp(_Attrib, "resizable")==0 )
3174 return BAR_RESIZABLE;
3175 else if( _stricmp(_Attrib, "movable")==0 )
3177 else if( _stricmp(_Attrib, "iconifiable")==0 )
3178 return BAR_ICONIFIABLE;
3179 else if( _stricmp(_Attrib, "fontresizable")==0 )
3180 return BAR_FONT_RESIZABLE;
3181 else if( _stricmp(_Attrib, "alwaystop")==0 )
3182 return BAR_ALWAYS_TOP;
3183 else if( _stricmp(_Attrib, "alwaysbottom")==0 )
3184 return BAR_ALWAYS_BOTTOM;
3185 else if( _stricmp(_Attrib, "visible")==0 )
3187 else if( _stricmp(_Attrib, "iconified")==0 )
3188 return BAR_ICONIFIED;
3189 else if( _stricmp(_Attrib, "colorscheme")==0 )
3190 return BAR_COLOR_SCHEME;
3191 else if( _stricmp(_Attrib, "contained")==0 )
3192 return BAR_CONTAINED;
3193 else if( _stricmp(_Attrib, "buttonalign")==0 )
3194 return BAR_BUTTON_ALIGN;
3197 if( _stricmp(_Attrib, "show")==0 ) // for backward compatibility
3199 else if( _stricmp(_Attrib, "hide")==0 ) // for backward compatibility
3201 else if( _stricmp(_Attrib, "iconify")==0 ) // for backward compatibility
3204 return 0; // not found
3207 int CTwBar::SetAttrib(int _AttribID, const char *_Value)
3212 if( _Value && strlen(_Value)>0 )
3220 g_TwMgr->SetLastError(g_ErrNoValue);
3224 if( _Value && strlen(_Value)>0 )
3232 g_TwMgr->SetLastError(g_ErrNoValue);
3236 if( _Value && strlen(_Value)>0 )
3239 int n = sscanf(_Value, "%d%d%d%d", &v0, &v1, &v2, &v3);
3241 int alpha = (m_Color>>24) & 0xff;
3242 if( n==3 && v0>=0 && v0<=255 && v1>=0 && v1<=255 && v2>=0 && v2<=255 )
3243 c = Color32FromARGBi(alpha, v0, v1, v2);
3244 else if( n==4 && v0>=0 && v0<=255 && v1>=0 && v1<=255 && v2>=0 && v2<=255 && v3>=0 && v3<=255 )
3245 c = Color32FromARGBi(v0, v1, v2, v3);
3248 g_TwMgr->SetLastError(g_ErrBadValue);
3257 g_TwMgr->SetLastError(g_ErrNoValue);
3261 if( _Value && strlen(_Value)>0 )
3264 int n = sscanf(_Value, "%d", &alpha);
3265 if( n==1 && alpha>=0 && alpha<=255 )
3266 m_Color = (alpha<<24) | (m_Color & 0xffffff);
3269 g_TwMgr->SetLastError(g_ErrBadValue);
3277 g_TwMgr->SetLastError(g_ErrNoValue);
3281 if( _Value && strlen(_Value)>0 )
3283 if( _stricmp(_Value, "dark")==0 )
3285 else if( _stricmp(_Value, "light")==0 )
3289 g_TwMgr->SetLastError(g_ErrBadValue);
3297 g_TwMgr->SetLastError(g_ErrNoValue);
3301 if( _Value && strlen(_Value)>0 )
3304 int n = sscanf(_Value, "%d%d", &sx, &sy);
3305 if( n==2 && sx>0 && sy>0 )
3314 g_TwMgr->SetLastError(g_ErrBadValue);
3320 g_TwMgr->SetLastError(g_ErrNoValue);
3324 if( _Value && strlen(_Value)>0 )
3327 int n = sscanf(_Value, "%d%d", &x, &y);
3328 if( n==2 && x>=0 && y>=0 )
3337 g_TwMgr->SetLastError(g_ErrBadValue);
3343 g_TwMgr->SetLastError(g_ErrNoValue);
3347 if( _Value && strlen(_Value)>0 )
3350 int n = sscanf(_Value, "%f", &r);
3358 g_TwMgr->SetLastError(g_ErrBadValue);
3364 g_TwMgr->SetLastError(g_ErrNoValue);
3367 case BAR_VALUES_WIDTH:
3368 if( _Value && strlen(_Value)>0 )
3370 if( _stricmp(_Value, "fit")==0 )
3372 m_ValuesWidth = VALUES_WIDTH_FIT;
3379 int n = sscanf(_Value, "%d", &w);
3388 g_TwMgr->SetLastError(g_ErrBadValue);
3395 g_TwMgr->SetLastError(g_ErrNoValue);
3399 return g_TwMgr->SetAttrib(MGR_FONT_SIZE, _Value);
3400 case BAR_FONT_STYLE:
3401 return g_TwMgr->SetAttrib(MGR_FONT_STYLE, _Value);
3403 return g_TwMgr->SetAttrib(MGR_ICON_POS, _Value);
3404 case BAR_ICON_ALIGN:
3405 return g_TwMgr->SetAttrib(MGR_ICON_ALIGN, _Value);
3406 case BAR_ICON_MARGIN:
3407 return g_TwMgr->SetAttrib(MGR_ICON_MARGIN, _Value);
3408 case BAR_SHOW: // deprecated
3409 TwSetBarState(this, TW_STATE_SHOWN);
3411 case BAR_HIDE: // deprecated
3412 TwSetBarState(this, TW_STATE_HIDDEN);
3414 case BAR_ICONIFY: // deprecated
3415 TwSetBarState(this, TW_STATE_ICONIFIED);
3418 if( _Value && strlen(_Value)>0 )
3420 if( _stricmp(_Value, "1")==0 || _stricmp(_Value, "true")==0 )
3425 else if( _stricmp(_Value, "0")==0 || _stricmp(_Value, "false")==0 )
3427 m_Resizable = false;
3432 g_TwMgr->SetLastError(g_ErrBadValue);
3438 g_TwMgr->SetLastError(g_ErrNoValue);
3442 if( _Value && strlen(_Value)>0 )
3444 if( _stricmp(_Value, "1")==0 || _stricmp(_Value, "true")==0 )
3449 else if( _stricmp(_Value, "0")==0 || _stricmp(_Value, "false")==0 )
3456 g_TwMgr->SetLastError(g_ErrBadValue);
3462 g_TwMgr->SetLastError(g_ErrNoValue);
3465 case BAR_ICONIFIABLE:
3466 if( _Value && strlen(_Value)>0 )
3468 if( _stricmp(_Value, "1")==0 || _stricmp(_Value, "true")==0 )
3470 m_Iconifiable = true;
3473 else if( _stricmp(_Value, "0")==0 || _stricmp(_Value, "false")==0 )
3475 m_Iconifiable = false;
3480 g_TwMgr->SetLastError(g_ErrBadValue);
3486 g_TwMgr->SetLastError(g_ErrNoValue);
3489 case BAR_FONT_RESIZABLE:
3490 return g_TwMgr->SetAttrib(MGR_FONT_RESIZABLE, _Value);
3491 case BAR_ALWAYS_TOP:
3492 if( _Value && strlen(_Value)>0 )
3494 if( _stricmp(_Value, "1")==0 || _stricmp(_Value, "true")==0 )
3496 g_TwMgr->m_BarAlwaysOnTop = m_Name;
3497 if( g_TwMgr->m_BarAlwaysOnBottom.length()>0 && strcmp(g_TwMgr->m_BarAlwaysOnBottom.c_str(), m_Name.c_str())==0 )
3498 g_TwMgr->m_BarAlwaysOnBottom.clear();
3502 else if( _stricmp(_Value, "0")==0 || _stricmp(_Value, "false")==0 )
3504 if( g_TwMgr->m_BarAlwaysOnTop.length()>0 && strcmp(g_TwMgr->m_BarAlwaysOnTop.c_str(), m_Name.c_str())==0 )
3505 g_TwMgr->m_BarAlwaysOnTop.clear();
3510 g_TwMgr->SetLastError(g_ErrBadValue);
3516 g_TwMgr->SetLastError(g_ErrNoValue);
3519 case BAR_ALWAYS_BOTTOM:
3520 if( _Value && strlen(_Value)>0 )
3522 if( _stricmp(_Value, "1")==0 || _stricmp(_Value, "true")==0 )
3524 g_TwMgr->m_BarAlwaysOnBottom = m_Name;
3525 if( g_TwMgr->m_BarAlwaysOnTop.length()>0 && strcmp(g_TwMgr->m_BarAlwaysOnTop.c_str(), m_Name.c_str())==0 )
3526 g_TwMgr->m_BarAlwaysOnTop.clear();
3527 TwSetBottomBar(this);
3530 else if( _stricmp(_Value, "0")==0 || _stricmp(_Value, "false")==0 )
3532 if( g_TwMgr->m_BarAlwaysOnBottom.length()>0 && strcmp(g_TwMgr->m_BarAlwaysOnBottom.c_str(), m_Name.c_str())==0 )
3533 g_TwMgr->m_BarAlwaysOnBottom.clear();
3538 g_TwMgr->SetLastError(g_ErrBadValue);
3544 g_TwMgr->SetLastError(g_ErrNoValue);
3548 if( _Value && strlen(_Value)>0 )
3550 if( _stricmp(_Value, "1")==0 || _stricmp(_Value, "true")==0 )
3552 TwSetBarState(this, TW_STATE_SHOWN);
3555 else if( _stricmp(_Value, "0")==0 || _stricmp(_Value, "false")==0 )
3557 TwSetBarState(this, TW_STATE_HIDDEN);
3562 g_TwMgr->SetLastError(g_ErrBadValue);
3568 g_TwMgr->SetLastError(g_ErrNoValue);
3572 if( _Value && strlen(_Value)>0 )
3574 if( _stricmp(_Value, "1")==0 || _stricmp(_Value, "true")==0 )
3576 TwSetBarState(this, TW_STATE_ICONIFIED);
3579 else if( _stricmp(_Value, "0")==0 || _stricmp(_Value, "false")==0 )
3581 TwSetBarState(this, TW_STATE_UNICONIFIED);
3586 g_TwMgr->SetLastError(g_ErrBadValue);
3592 g_TwMgr->SetLastError(g_ErrNoValue);
3595 case BAR_COLOR_SCHEME:
3596 return g_TwMgr->SetAttrib(MGR_COLOR_SCHEME, _Value);
3598 if( _Value && strlen(_Value)>0 )
3600 if( _stricmp(_Value, "1")==0 || _stricmp(_Value, "true")==0 )
3605 else if( _stricmp(_Value, "0")==0 || _stricmp(_Value, "false")==0 )
3607 m_Contained = false;
3612 g_TwMgr->SetLastError(g_ErrBadValue);
3618 g_TwMgr->SetLastError(g_ErrNoValue);
3621 case BAR_BUTTON_ALIGN:
3622 if( _Value && strlen(_Value)>0 )
3624 if( _stricmp(_Value, "left")==0 )
3626 m_ButtonAlign = BUTTON_ALIGN_LEFT;
3629 else if( _stricmp(_Value, "center")==0 )
3631 m_ButtonAlign = BUTTON_ALIGN_CENTER;
3634 if( _stricmp(_Value, "right")==0 )
3636 m_ButtonAlign = BUTTON_ALIGN_RIGHT;
3641 g_TwMgr->SetLastError(g_ErrBadValue);
3647 g_TwMgr->SetLastError(g_ErrNoValue);
3651 g_TwMgr->SetLastError(g_ErrUnknownAttrib);
3656 ERetType CTwBar::GetAttrib(int _AttribID, std::vector<double>& outDoubles, std::ostringstream& outString) const
3664 outString << m_Label;
3667 outString << m_Help;
3673 Color32ToARGBi(m_Color, &a, &r, &g, &b);
3674 outDoubles.push_back(r);
3675 outDoubles.push_back(g);
3676 outDoubles.push_back(b);
3683 Color32ToARGBi(m_Color, &a, &r, &g, &b);
3684 outDoubles.push_back(a);
3689 outString << "dark";
3691 outString << "light";
3694 outDoubles.push_back(m_Width);
3695 outDoubles.push_back(m_Height);
3698 outDoubles.push_back(m_PosX);
3699 outDoubles.push_back(m_PosY);
3702 outDoubles.push_back(m_UpdatePeriod);
3704 case BAR_VALUES_WIDTH:
3705 outDoubles.push_back(m_ValuesWidth);
3708 return g_TwMgr->GetAttrib(MGR_FONT_SIZE, outDoubles, outString);
3709 case BAR_FONT_STYLE:
3710 return g_TwMgr->GetAttrib(MGR_FONT_STYLE, outDoubles, outString);
3712 return g_TwMgr->GetAttrib(MGR_ICON_POS, outDoubles, outString);
3713 case BAR_ICON_ALIGN:
3714 return g_TwMgr->GetAttrib(MGR_ICON_ALIGN, outDoubles, outString);
3715 case BAR_ICON_MARGIN:
3716 return g_TwMgr->GetAttrib(MGR_ICON_MARGIN, outDoubles, outString);
3718 outDoubles.push_back(m_Resizable);
3721 outDoubles.push_back(m_Movable);
3723 case BAR_ICONIFIABLE:
3724 outDoubles.push_back(m_Iconifiable);
3726 case BAR_FONT_RESIZABLE:
3727 return g_TwMgr->GetAttrib(MGR_FONT_RESIZABLE, outDoubles, outString);
3728 case BAR_ALWAYS_TOP:
3729 outDoubles.push_back( g_TwMgr->m_BarAlwaysOnTop == m_Name );
3731 case BAR_ALWAYS_BOTTOM:
3732 outDoubles.push_back( g_TwMgr->m_BarAlwaysOnBottom == m_Name );
3735 outDoubles.push_back(m_Visible);
3738 outDoubles.push_back(m_IsMinimized);
3740 case BAR_COLOR_SCHEME:
3741 return g_TwMgr->GetAttrib(MGR_COLOR_SCHEME, outDoubles, outString);
3743 outDoubles.push_back(m_Contained);
3745 case BAR_BUTTON_ALIGN:
3746 if( m_ButtonAlign==BUTTON_ALIGN_LEFT )
3747 outString << "left";
3748 else if( m_ButtonAlign==BUTTON_ALIGN_CENTER )
3749 outString << "center";
3751 outString << "right";
3754 g_TwMgr->SetLastError(g_ErrUnknownAttrib);
3759 // ---------------------------------------------------------------------------
3761 void CTwBar::NotUpToDate()
3766 // ---------------------------------------------------------------------------
3768 void CTwBar::UpdateColors()
3770 float a, r, g, b, h, l, s;
3771 Color32ToARGBf(m_Color, &a, &r, &g, &b);
3772 ColorRGBToHLSf(r, g, b, &h, &l, &s);
3773 bool lightText = !m_DarkText;
3775 // Colors independant of m_Color
3777 // Highlighted line background ramp
3778 m_ColHighBg0 = lightText ? Color32FromARGBf(0.4f, 0.9f, 0.9f, 0.9f) : Color32FromARGBf(0.4f, 1.0f, 1.0f, 1.0f);
3779 m_ColHighBg1 = lightText ? Color32FromARGBf(0.4f, 0.2f, 0.2f, 0.2f) : Color32FromARGBf(0.1f, 0.7f, 0.7f, 0.7f);
3781 // Text colors & background
3782 m_ColLabelText = lightText ? COLOR32_WHITE : COLOR32_BLACK;
3783 m_ColStructText = lightText ? 0xffefef00 : 0xff303000;
3785 m_ColValText = lightText ? 0xffc7d7ff : 0xff000080;
3786 m_ColValTextRO = lightText ? 0xffb7b7b7 : 0xff505050;
3787 m_ColValMin = lightText ? 0xff9797ff : 0xff0000f0;
3788 m_ColValMax = m_ColValMin;
3789 m_ColValTextNE = lightText ? 0xff97f797 : 0xff004000;
3791 m_ColValBg = lightText ? Color32FromARGBf(0.2f+0.3f*a, 0.1f, 0.1f, 0.1f) : Color32FromARGBf(0.2f+0.3f*a, 1, 1, 1);
3792 m_ColStructBg = lightText ? Color32FromARGBf(0.4f*a, 0, 0, 0) : Color32FromARGBf(0.4f*a, 1, 1, 1);
3794 m_ColLine = lightText ? Color32FromARGBf(0.6f, 1, 1, 1) : Color32FromARGBf(0.6f, 0.3f, 0.3f, 0.3f);
3795 m_ColLineShadow = lightText ? Color32FromARGBf(0.6f, 0, 0, 0) : Color32FromARGBf(0.6f, 0, 0, 0);
3796 m_ColUnderline = lightText ? 0xffd0d0d0 : 0xff202000;
3798 m_ColGrpBg = lightText ? Color32FromARGBf(0.1f+0.25f*a, 1, 1, 1) : Color32FromARGBf(0.1f+0.05f*a, 0, 0, 0);
3799 m_ColGrpText = lightText ? 0xffffff80 : 0xff000000;
3801 m_ColShortcutText = lightText ? 0xffffb060 : 0xff802000;
3802 m_ColShortcutBg = lightText ? Color32FromARGBf(0.4f*a, 0.2f, 0.2f, 0.2f) : Color32FromARGBf(0.4f*a, 0.8f, 0.8f, 0.8f);
3803 m_ColInfoText = lightText ? Color32FromARGBf(1.0f, 0.7f, 0.7f, 0.7f) : Color32FromARGBf(1.0f, 0.3f, 0.3f, 0.3f);
3805 m_ColRoto = lightText ? Color32FromARGBf(0.8f, 0.85f, 0.85f, 0.85f) : Color32FromARGBf(0.8f, 0.1f, 0.1f, 0.1f);
3806 m_ColRotoVal = Color32FromARGBf(1, 1.0f, 0.2f, 0.2f);
3807 m_ColRotoBound = lightText ? Color32FromARGBf(0.8f, 0.6f, 0.6f, 0.6f) : Color32FromARGBf(0.8f, 0.3f, 0.3f, 0.3f);
3809 m_ColEditText = lightText ? COLOR32_WHITE : COLOR32_BLACK;
3810 m_ColEditBg = lightText ? 0xff575757 : 0xffc7c7c7; // must be opaque
3811 m_ColEditSelText = lightText ? COLOR32_BLACK : COLOR32_WHITE;
3812 m_ColEditSelBg = lightText ? 0xffc7c7c7 : 0xff575757;
3814 // Colors dependant of m_Colors
3817 ColorHLSToRGBf(h, l, s, &r, &g, &b);
3818 m_ColBg = Color32FromARGBf(a, r, g, b);
3819 ColorHLSToRGBf(h, l-0.05f, s, &r, &g, &b);
3820 m_ColBg1 = Color32FromARGBf(a, r, g, b);
3821 ColorHLSToRGBf(h, l-0.1f, s, &r, &g, &b);
3822 m_ColBg2 = Color32FromARGBf(a, r, g, b);
3824 ColorHLSToRGBf(h, l-0.15f, s, &r, &g, &b);
3825 m_ColTitleBg = Color32FromARGBf(a+0.9f, r, g, b);
3826 m_ColTitleText = lightText ? COLOR32_WHITE : COLOR32_BLACK;
3827 m_ColTitleShadow = lightText ? 0x40000000 : 0x00000000;
3828 ColorHLSToRGBf(h, l-0.25f, s, &r, &g, &b);
3829 m_ColTitleHighBg = Color32FromARGBf(a+0.8f, r, g, b);
3830 ColorHLSToRGBf(h, l-0.3f, s, &r, &g, &b);
3831 m_ColTitleUnactiveBg = Color32FromARGBf(a+0.2f, r, g, b);
3833 ColorHLSToRGBf(h, l-0.2f, s, &r, &g, &b);
3834 m_ColHierBg = Color32FromARGBf(a, r, g, b);
3836 ColorHLSToRGBf(h, l+0.1f, s, &r, &g, &b);
3837 m_ColBtn = Color32FromARGBf(0.2f+0.4f*a, r, g, b);
3838 ColorHLSToRGBf(h, l-0.35f, s, &r, &g, &b);
3839 m_ColHighBtn = Color32FromARGBf(0.4f+0.4f*a, r, g, b);
3840 ColorHLSToRGBf(h, l-0.25f, s, &r, &g, &b);
3841 m_ColFold = Color32FromARGBf(0.1f+0.4f*a, r, g, b);
3842 ColorHLSToRGBf(h, l-0.35f, s, &r, &g, &b);
3843 m_ColHighFold = Color32FromARGBf(0.3f+0.4f*a, r, g, b);
3845 ColorHLSToRGBf(h, 0.75f, s, &r, &g, &b);
3846 m_ColHelpBg = Color32FromARGBf(0.2f, 1, 1, 1);
3847 m_ColHelpText = lightText ? Color32FromARGBf(1, 0.2f, 1.0f, 0.2f) : Color32FromARGBf(1, 0, 0.4f, 0);
3848 m_ColSeparator = m_ColValTextRO;
3849 m_ColStaticText = m_ColHelpText;
3853 void CTwBar::UpdateColors()
3855 float a, r, g, b, h, l, s;
3856 Color32ToARGBf(m_Color, &a, &r, &g, &b);
3857 ColorRGBToHLSf(r, g, b, &h, &l, &s);
3858 bool lightText = !m_DarkText; // (l<=0.45f);
3861 ColorHLSToRGBf(h, l, s, &r, &g, &b);
3862 m_ColBg = Color32FromARGBf(a, r, g, b);
3863 ColorHLSToRGBf(h, l-0.1f, s, &r, &g, &b);
3864 m_ColBg1 = Color32FromARGBf(a, r, g, b);
3865 ColorHLSToRGBf(h, l-0.2f, s, &r, &g, &b);
3866 m_ColBg2 = Color32FromARGBf(a, r, g, b);
3868 ColorHLSToRGBf(h, l+0.1f, s, &r, &g, &b);
3869 m_ColHighBg = Color32FromARGBf(0.4f, r, g, b);
3870 //m_ColHighBg = Color32FromARGBf(a, 0.95f, 0.95f, 0.2f);
3872 m_ColLabelText = lightText ? COLOR32_WHITE : COLOR32_BLACK;
3873 m_ColStructText = lightText ? 0xffefef00 : 0xff505000;
3875 m_ColValText = lightText ? 0xffb7b7ff : 0xff000080;
3876 m_ColValTextRO = lightText ? 0xffb7b7b7 : 0xff505050;
3877 m_ColValMin = lightText ? 0xff9797ff : 0xff0000f0;
3878 m_ColValMax = m_ColValMin;
3879 m_ColValTextNE = lightText ? 0xff97f797 : 0xff006000;
3881 ColorHLSToRGBf(h, lightText ? (min(l+0.2f, 0.3f)) : (max(l-0.2f, 0.6f)), s, &r, &g, &b);
3882 m_ColValBg = Color32FromARGBf(0.4f*a, 0, 0, 0);
3883 m_ColStructBg = Color32FromARGBf(0.4f*a, 0, 0, 0);
3885 ColorHLSToRGBf(h, 0.4f, s, &r, &g, &b);
3886 m_ColTitleBg = Color32FromARGBf(a+0.4f, r, g, b);
3887 m_ColTitleText = lightText ? COLOR32_WHITE : COLOR32_BLACK;
3888 m_ColTitleShadow = lightText ? 0x80000000 : 0x80ffffff;
3889 ColorHLSToRGBf(h, 0.3f, s, &r, &g, &b);
3890 m_ColTitleHighBg = Color32FromARGBf(a+0.4f, r, g, b);
3891 ColorHLSToRGBf(h, 0.4f, s, &r, &g, &b);
3892 m_ColTitleUnactiveBg = Color32FromARGBf(a+0.2f, r, g, b);
3894 ColorHLSToRGBf(h, 0.8f, s, &r, &g, &b);
3895 m_ColLine = Color32FromARGBf(0.6f, r, g, b); // 0xfff0f0f0;
3896 m_ColLineShadow = Color32FromARGBf(0.6f, 0, 0, 0); //COLOR32_BLACK;
3897 m_ColUnderline = lightText ? 0xffd0d0d0 : 0xff202000;
3898 ColorHLSToRGBf(h, 0.7f, s, &r, &g, &b);
3899 m_ColBtn = Color32FromARGBf(0.6f, r, g, b);
3900 ColorHLSToRGBf(h, 0.4f, s, &r, &g, &b);
3901 m_ColHighBtn = Color32FromARGBf(0.6f, r, g, b);
3902 ColorHLSToRGBf(h, 0.6f, s, &r, &g, &b);
3903 m_ColFold = Color32FromARGBf(0.3f*a, r, g, b);
3904 ColorHLSToRGBf(h, 0.4f, s, &r, &g, &b);
3905 m_ColHighFold = Color32FromARGBf(0.3f, r, g, b);
3907 ColorHLSToRGBf(h, lightText ? l+0.2f : l-0.2f, s, &r, &g, &b);
3908 m_ColGrpBg = Color32FromARGBf(0.5f*a, r, g, b);
3909 m_ColGrpText = lightText ? 0xffffff80 : 0xff404000;
3911 ColorHLSToRGBf(h, 0.75f, s, &r, &g, &b);
3912 m_ColHelpBg = Color32FromARGBf(a, r, g, b);
3913 m_ColHelpText = Color32FromARGBf(1, 0, 0.4f, 0);
3915 ColorHLSToRGBf(h, 0.45f, s, &r, &g, &b);
3916 m_ColHierBg = Color32FromARGBf(0.75f*a, r, g, b);
3918 m_ColShortcutText = lightText ? 0xffff8040 : 0xff802000; //0xfff0f0f0;
3919 m_ColShortcutBg = Color32FromARGBf(0.4f*a, 0.2f, 0.2f, 0.2f);
3920 m_ColInfoText = Color32FromARGBf(1.0f, 0.7f, 0.7f, 0.7f);
3922 m_ColRoto = Color32FromARGBf(1, 0.75f, 0.75f, 0.75f);
3923 m_ColRotoVal = Color32FromARGBf(1, 1.0f, 0.2f, 0.2f);
3924 m_ColRotoBound = Color32FromARGBf(1, 0.4f, 0.4f, 0.4f);
3926 m_ColEditText = lightText ? COLOR32_WHITE : COLOR32_BLACK;
3927 m_ColEditBg = lightText ? 0xb7575757 : 0xb7c7c7c7;
3928 m_ColEditSelText = lightText ? COLOR32_BLACK : COLOR32_WHITE;
3929 m_ColEditSelBg = lightText ? 0xffc7c7c7 : 0xff575757;
3931 m_ColSeparator = m_ColValTextRO;
3932 m_ColStaticText = m_ColHelpText;
3936 // ---------------------------------------------------------------------------
3938 CTwVarGroup::~CTwVarGroup()
3940 for( vector<CTwVar*>::iterator it= m_Vars.begin(); it!=m_Vars.end(); ++it )
3949 // ---------------------------------------------------------------------------
3951 static inline int IncrBtnWidth(int _CharHeight)
3953 return ((2*_CharHeight)/3+2)&0xfffe; // force even value
3956 // ---------------------------------------------------------------------------
3958 void CTwBar::BrowseHierarchy(int *_CurrLine, int _CurrLevel, const CTwVar *_Var, int _First, int _Last)
3961 if( !_Var->m_IsRoot )
3963 if( (*_CurrLine)>=_First && (*_CurrLine)<=_Last )
3966 Tag.m_Level = _CurrLevel;
3967 Tag.m_Var = const_cast<CTwVar *>(_Var);
3968 Tag.m_Closing = false;
3969 m_HierTags.push_back(Tag);
3977 m_HierTags.resize(0);
3980 if( _Var->IsGroup() )
3982 const CTwVarGroup *Grp = static_cast<const CTwVarGroup *>(_Var);
3984 for( vector<CTwVar*>::const_iterator it=Grp->m_Vars.begin(); it!=Grp->m_Vars.end(); ++it )
3985 if( (*it)->m_Visible )
3986 BrowseHierarchy(_CurrLine, _CurrLevel+1, *it, _First, _Last);
3987 if( m_HierTags.size()>0 )
3988 m_HierTags[m_HierTags.size()-1].m_Closing = true;
3992 // ---------------------------------------------------------------------------
3994 void CTwBar::ListLabels(vector<string>& _Labels, vector<color32>& _Colors, vector<color32>& _BgColors, bool *_HasBgColors, const CTexFont *_Font, int _AtomWidthMax, int _GroupWidthMax)
3996 const int NbEtc = 2;
3998 int Len, i, x, Etc, s;
3999 const unsigned char *Text;
4003 int Space = _Font->m_CharWidth[(int)' '];
4004 int LevelSpace = max(_Font->m_CharHeight-6, 4); // space used by DrawHierHandles
4006 int nh = (int)m_HierTags.size();
4007 for( int h=0; h<nh; ++h )
4009 Len = (int)m_HierTags[h].m_Var->m_Label.length();
4011 Text = (const unsigned char *)(m_HierTags[h].m_Var->m_Label.c_str());
4014 Text = (const unsigned char *)(m_HierTags[h].m_Var->m_Name.c_str());
4015 Len = (int)m_HierTags[h].m_Var->m_Name.length();
4019 _Labels.push_back(""); // add a new text line
4020 if( !m_HierTags[h].m_Var->IsGroup() && static_cast<const CTwVarAtom *>(m_HierTags[h].m_Var)->m_Type==TW_TYPE_BUTTON && static_cast<const CTwVarAtom *>(m_HierTags[h].m_Var)->m_ReadOnly && static_cast<const CTwVarAtom *>(m_HierTags[h].m_Var)->m_Val.m_Button.m_Callback!=NULL )
4021 _Colors.push_back(m_ColValTextRO); // special case for read-only buttons
4023 _Colors.push_back(m_HierTags[h].m_Var->m_ColorPtr!=NULL ? *(m_HierTags[h].m_Var->m_ColorPtr) : COLOR32_WHITE);
4024 color32 bg = m_HierTags[h].m_Var->m_BgColorPtr!=NULL ? *(m_HierTags[h].m_Var->m_BgColorPtr) : 0;
4025 _BgColors.push_back(bg);
4026 if( _HasBgColors!=NULL && bg!=0 )
4027 *_HasBgColors = true;
4028 bool IsCustom = m_HierTags[h].m_Var->IsCustom(); // !m_HierTags[h].m_Var->IsGroup() && (static_cast<const CTwVarAtom *>(m_HierTags[h].m_Var)->m_Type>=TW_TYPE_CUSTOM_BASE && static_cast<const CTwVarAtom *>(m_HierTags[h].m_Var)->m_Type<TW_TYPE_CUSTOM_BASE+(int)g_TwMgr->m_Customs.size());
4031 string& CurrentLabel = _Labels[_Labels.size()-1];
4032 if( m_HierTags[h].m_Var->IsGroup() && static_cast<const CTwVarGroup *>(m_HierTags[h].m_Var)->m_SummaryCallback==NULL )
4033 WidthMax = _GroupWidthMax;
4034 else if( !m_HierTags[h].m_Var->IsGroup() && static_cast<const CTwVarAtom *>(m_HierTags[h].m_Var)->m_Type==TW_TYPE_BUTTON )
4036 if( static_cast<const CTwVarAtom *>(m_HierTags[h].m_Var)->m_Val.m_Button.m_Callback==NULL )
4037 WidthMax = _GroupWidthMax;
4038 else if( m_ButtonAlign == BUTTON_ALIGN_RIGHT )
4039 WidthMax = _GroupWidthMax - 2*IncrBtnWidth(m_Font->m_CharHeight);
4041 WidthMax = _AtomWidthMax;
4043 //else if( m_HighlightedLine==h && m_DrawRotoBtn )
4044 // WidthMax = _AtomWidthMax - IncrBtnWidth(m_Font->m_CharHeight);
4046 WidthMax = _AtomWidthMax;
4048 for( s=0; s<m_HierTags[h].m_Level*LevelSpace; s+=Space )
4050 CurrentLabel += ' ';
4053 if( x+(NbEtc+2)*_Font->m_CharWidth[(int)'.']<WidthMax || m_HierTags[h].m_Var->m_DontClip)
4054 for( i=0; i<Len; ++i )
4056 ch = (Etc==0) ? Text[i] : '.';
4058 x += _Font->m_CharWidth[(int)ch];
4065 else if( i<Len-2 && x+(NbEtc+2)*_Font->m_CharWidth[(int)'.']>=WidthMax && !(m_HierTags[h].m_Var->m_DontClip))
4072 // ---------------------------------------------------------------------------
4074 void CTwBar::ListValues(vector<string>& _Values, vector<color32>& _Colors, vector<color32>& _BgColors, const CTexFont *_Font, int _WidthMax)
4076 CTwFPU fpu; // force fpu precision
4078 const int NbEtc = 2;
4079 const CTwVarAtom *Atom = NULL;
4082 const unsigned char *Text;
4090 size_t SummaryMaxLength = max(_WidthMax/_Font->m_CharWidth[(int)'I'], 4);
4091 static vector<char> Summary;
4092 Summary.resize(SummaryMaxLength+32);
4094 int nh = (int)m_HierTags.size();
4095 for( int h=0; h<nh; ++h )
4096 if( !m_HierTags[h].m_Var->IsGroup() || m_IsHelpBar
4097 || (m_HierTags[h].m_Var->IsGroup() && static_cast<const CTwVarGroup *>(m_HierTags[h].m_Var)->m_SummaryCallback!=NULL) )
4105 if( !m_HierTags[h].m_Var->IsGroup() )
4107 Atom = static_cast<const CTwVarAtom *>(m_HierTags[h].m_Var);
4108 Atom->ValueToString(&ValStr);
4109 if( !m_IsHelpBar || (Atom->m_Type==TW_TYPE_SHORTCUT && (Atom->m_Val.m_Shortcut.m_Incr[0]>0 || Atom->m_Val.m_Shortcut.m_Decr[0]>0)) )
4110 ReadOnly = Atom->m_ReadOnly;
4111 if( !Atom->m_NoSlider )
4113 double v, vmin, vmax;
4114 v = Atom->ValueToDouble();
4115 Atom->MinMaxStepToDouble(&vmin, &vmax, NULL);
4119 if( Atom->m_Type==TW_TYPE_BOOLCPP || Atom->m_Type==TW_TYPE_BOOL8 || Atom->m_Type==TW_TYPE_BOOL16 || Atom->m_Type==TW_TYPE_BOOL32 )
4122 ValStr = "\x7f"; // check sign
4123 else if (ValStr=="0")
4124 ValStr = " -"; //"\x97"; // uncheck sign
4126 if( (Atom->m_Type==TW_TYPE_CDSTRING && Atom->m_SetCallback==NULL && g_TwMgr->m_CopyCDStringToClient==NULL)
4127 || (Atom->m_Type==TW_TYPE_CDSTDSTRING && Atom->m_SetCallback==NULL)
4128 || (Atom->m_Type==TW_TYPE_STDSTRING && Atom->m_SetCallback==NULL && g_TwMgr->m_CopyStdStringToClient==NULL) )
4130 if( Atom->m_Type==TW_TYPE_HELP_ATOM || Atom->m_Type==TW_TYPE_HELP_GRP || Atom->m_Type==TW_TYPE_BUTTON || Atom->IsCustom() ) // (Atom->m_Type>=TW_TYPE_CUSTOM_BASE && Atom->m_Type<TW_TYPE_CUSTOM_BASE+(int)g_TwMgr->m_Customs.size()) )
4132 AcceptEdit = EditInPlaceAcceptVar(Atom) || (Atom->m_Type==TW_TYPE_SHORTCUT);
4134 else if(m_HierTags[h].m_Var->IsGroup() && static_cast<const CTwVarGroup *>(m_HierTags[h].m_Var)->m_SummaryCallback!=NULL)
4136 const CTwVarGroup *Grp = static_cast<const CTwVarGroup *>(m_HierTags[h].m_Var);
4137 // force internal value update
4138 for( size_t v=0; v<Grp->m_Vars.size(); v++ )
4139 if( Grp->m_Vars[v]!=NULL && !Grp->m_Vars[v]->IsGroup() && Grp->m_Vars[v]->m_Visible )
4140 static_cast<CTwVarAtom *>(Grp->m_Vars[v])->ValueToDouble();
4143 if( Grp->m_SummaryCallback==CTwMgr::CStruct::DefaultSummary )
4144 Grp->m_SummaryCallback(&Summary[0], SummaryMaxLength, Grp, Grp->m_SummaryClientData);
4146 Grp->m_SummaryCallback(&Summary[0], SummaryMaxLength, Grp->m_StructValuePtr, Grp->m_SummaryClientData);
4147 ValStr = (const char *)(&Summary[0]);
4151 ValStr = ""; // is a group in the help bar
4154 Len = (int)ValStr.length();
4155 Text = (const unsigned char *)(ValStr.c_str());
4158 _Values.push_back(""); // add a new text line
4159 if( ReadOnly || (IsMin && IsMax) || IsROText )
4160 _Colors.push_back(m_ColValTextRO);
4162 _Colors.push_back(m_ColValMin);
4164 _Colors.push_back(m_ColValMax);
4165 else if( !AcceptEdit )
4166 _Colors.push_back(m_ColValTextNE);
4168 _Colors.push_back(m_ColValText);
4170 _BgColors.push_back(0x00000000);
4171 else if( m_HierTags[h].m_Var->IsGroup() )
4173 const CTwVarGroup *Grp = static_cast<const CTwVarGroup *>(m_HierTags[h].m_Var);
4174 // if typecolor set bgcolor
4175 if( Grp->m_SummaryCallback==CColorExt::SummaryCB )
4176 _BgColors.push_back(0xff000000);
4178 _BgColors.push_back(m_ColStructBg);
4181 _BgColors.push_back(m_ColValBg);
4183 string& CurrentValue = _Values[_Values.size()-1];
4184 int wmax = _WidthMax;
4185 if( m_HighlightedLine==h && m_DrawRotoBtn )
4186 wmax -= 3*IncrBtnWidth(m_Font->m_CharHeight);
4187 else if( m_HighlightedLine==h && m_DrawIncrDecrBtn )
4188 wmax -= 2*IncrBtnWidth(m_Font->m_CharHeight);
4189 else if( m_HighlightedLine==h && m_DrawListBtn )
4190 wmax -= 1*IncrBtnWidth(m_Font->m_CharHeight);
4191 else if( m_HighlightedLine==h && m_DrawBoolBtn )
4192 wmax -= 1*IncrBtnWidth(m_Font->m_CharHeight);
4193 for( i=0; i<Len; ++i )
4195 ch = (Etc==0) ? Text[i] : '.';
4197 x += _Font->m_CharWidth[(int)ch];
4204 else if( i<Len-2 && x+(NbEtc+2)*(_Font->m_CharWidth[(int)'.'])>=wmax )
4210 _Values.push_back(""); // add a new empty line
4211 _Colors.push_back(COLOR32_BLACK);
4212 _BgColors.push_back(0x00000000);
4216 // ---------------------------------------------------------------------------
4218 int CTwBar::ComputeLabelsWidth(const CTexFont *_Font)
4221 const unsigned char *Text;
4222 int LabelsWidth = 0;
4223 int Space = _Font->m_CharWidth[(int)' '];
4224 int LevelSpace = max(_Font->m_CharHeight-6, 4); // space used by DrawHierHandles
4226 int nh = (int)m_HierTags.size();
4227 for( int h=0; h<nh; ++h )
4229 Len = (int)m_HierTags[h].m_Var->m_Label.length();
4231 Text = (const unsigned char *)(m_HierTags[h].m_Var->m_Label.c_str());
4234 Text = (const unsigned char *)(m_HierTags[h].m_Var->m_Name.c_str());
4235 Len = (int)m_HierTags[h].m_Var->m_Name.length();
4238 bool IsCustom = m_HierTags[h].m_Var->IsCustom(); // !m_HierTags[h].m_Var->IsGroup() && (static_cast<const CTwVarAtom *>(m_HierTags[h].m_Var)->m_Type>=TW_TYPE_CUSTOM_BASE && static_cast<const CTwVarAtom *>(m_HierTags[h].m_Var)->m_Type<TW_TYPE_CUSTOM_BASE+(int)g_TwMgr->m_Customs.size());
4242 for( s=0; s<m_HierTags[h].m_Level*LevelSpace; s+=Space )
4244 for( i=0; i<Len; ++i )
4245 x += _Font->m_CharWidth[(int)Text[i]];
4246 x += 3*Space; // add little margin
4248 if (x > LabelsWidth)
4255 int CTwBar::ComputeValuesWidth(const CTexFont *_Font)
4257 CTwFPU fpu; // force fpu precision
4259 const CTwVarAtom *Atom = NULL;
4262 int Space = _Font->m_CharWidth[(int)' '];
4263 const unsigned char *Text;
4264 int ValuesWidth = 0;
4266 int nh = (int)m_HierTags.size();
4267 for( int h=0; h<nh; ++h )
4268 if( !m_HierTags[h].m_Var->IsGroup() )
4270 Atom = static_cast<const CTwVarAtom *>(m_HierTags[h].m_Var);
4271 Atom->ValueToString(&ValStr);
4273 Len = (int)ValStr.length();
4274 Text = (const unsigned char *)(ValStr.c_str());
4276 for( i=0; i<Len; ++i )
4277 x += _Font->m_CharWidth[(int)Text[i]];
4278 x += 2*Space; // add little margin
4279 if (x > ValuesWidth)
4286 // ---------------------------------------------------------------------------
4288 static int ClampText(string& _Text, const CTexFont *_Font, int _WidthMax)
4290 int Len = (int)_Text.length();
4294 for( i=0; i<Len; ++i )
4297 if( i<Len-1 && Width+_Font->m_CharWidth[(int)'.']>=_WidthMax )
4299 Width += _Font->m_CharWidth[ch];
4301 if( i<Len ) // clamp
4304 _Text.at(i+0) = '.';
4305 _Text.at(i+1) = '.';
4306 Width += 2*_Font->m_CharWidth[(int)'.'];
4311 // ---------------------------------------------------------------------------
4313 void CTwBar::Update()
4315 assert(m_UpToDate==false);
4317 ITwGraph *Gr = g_TwMgr->m_Graph;
4319 bool DoEndDraw = false;
4320 if( !Gr->IsDrawing() )
4322 Gr->BeginDraw(g_TwMgr->m_WndWidth, g_TwMgr->m_WndHeight);
4326 bool ValuesWidthFit = false;
4327 if( m_ValuesWidth==VALUES_WIDTH_FIT )
4329 ValuesWidthFit = true;
4332 int PrevPosY = m_PosY;
4333 int vpx, vpy, vpw, vph;
4336 vpw = g_TwMgr->m_WndWidth;
4337 vph = g_TwMgr->m_WndHeight;
4338 if( !m_IsMinimized && vpw>0 && vph>0 )
4343 if( m_Width>vpw && m_Contained )
4348 if( m_Width<8*m_Font->m_CharHeight )
4350 m_Width = 8*m_Font->m_CharHeight;
4353 if( m_Height>vph && m_Contained )
4358 if( m_Height<5*m_Font->m_CharHeight )
4360 m_Height = 5*m_Font->m_CharHeight;
4364 if( m_Movable && m_Contained )
4366 if( m_PosX+m_Width>vpx+vpw )
4367 m_PosX = vpx+vpw-m_Width;
4370 if( m_PosY+m_Height>vpy+vph )
4371 m_PosY = vpy+vph-m_Height;
4375 m_ScrollY0 += m_PosY-PrevPosY;
4376 m_ScrollY1 += m_PosY-PrevPosY;
4377 if( m_ValuesWidth<2*m_Font->m_CharHeight )
4379 m_ValuesWidth = 2*m_Font->m_CharHeight;
4382 if( m_ValuesWidth>m_Width-4*m_Font->m_CharHeight )
4384 m_ValuesWidth = m_Width-4*m_Font->m_CharHeight;
4389 if( Modif && m_IsHelpBar )
4391 g_TwMgr->m_HelpBarNotUpToDate = true;
4392 g_TwMgr->m_KeyPressedBuildText = true;
4393 g_TwMgr->m_InfoBuildText = true;
4399 // update geometry relatively to (m_PosX, m_PosY)
4400 if( !m_IsPopupList )
4402 //m_VarX0 = 2*m_Font->m_CharHeight+m_Sep;
4403 m_VarX0 = m_Font->m_CharHeight+m_Sep;
4404 //m_VarX2 = m_Width - 4;
4405 m_VarX2 = m_Width - m_Font->m_CharHeight - m_Sep-2;
4406 m_VarX1 = m_VarX2 - m_ValuesWidth;
4410 //m_VarX0 = m_Font->m_CharHeight+6+m_Sep;
4412 //m_VarX2 = m_Width - 4;
4413 m_VarX2 = m_Width - m_Font->m_CharHeight - m_Sep-2;
4416 if( m_VarX1<m_VarX0+32 )
4417 m_VarX1 = m_VarX0+32;
4418 if( m_VarX1>m_VarX2 )
4420 if( !m_IsPopupList )
4422 m_VarY0 = m_Font->m_CharHeight+2+m_Sep+6;
4423 m_VarY1 = m_Height-m_Font->m_CharHeight-2-m_Sep;
4424 m_VarY2 = m_Height-1;
4429 m_VarY1 = m_Height-2-m_Sep;
4430 m_VarY2 = m_Height-1;
4433 int NbLines = (m_VarY1-m_VarY0+1)/(m_Font->m_CharHeight+m_LineSep);
4436 if( !m_IsMinimized )
4439 BrowseHierarchy(&LineNum, 0, &m_VarRoot, m_FirstLine, m_FirstLine+NbLines); // add a dummy tag at the end to avoid wrong 'tag-closing' problems
4440 if( (int)m_HierTags.size()>NbLines )
4441 m_HierTags.resize(NbLines); // remove the last dummy tag
4442 m_NbHierLines = LineNum;
4443 m_NbDisplayedLines = (int)m_HierTags.size();
4445 if( ValuesWidthFit )
4447 m_ValuesWidth = ComputeValuesWidth(m_Font);
4448 if( m_ValuesWidth<2*m_Font->m_CharHeight )
4449 m_ValuesWidth = 2*m_Font->m_CharHeight; // enough to draw buttons
4450 if( m_ValuesWidth>m_VarX2 - m_VarX0 )
4451 m_ValuesWidth = max(m_VarX2 - m_VarX0 - m_Font->m_CharHeight, 0);
4452 m_VarX1 = m_VarX2 - m_ValuesWidth;
4453 if( m_VarX1<m_VarX0+32 )
4454 m_VarX1 = m_VarX0+32;
4455 if( m_VarX1>m_VarX2 )
4457 m_ValuesWidth = m_VarX2 - m_VarX1;
4462 int y0 = m_PosY+m_VarY0;
4463 int y1 = m_PosY+m_VarY1;
4465 int x1 = m_PosX+m_Font->m_CharHeight-2;
4466 if( ((x0+x1)&1)==1 )
4470 int hscr = (m_NbHierLines>0) ? ((h*m_NbDisplayedLines)/m_NbHierLines) : h;
4475 int yscr = (m_NbHierLines>0) ? ((h*m_FirstLine)/m_NbHierLines) : 0;
4488 m_ScrollY0 = y0+w+yscr;
4489 m_ScrollY1 = y0+w+yscr+hscr;
4493 if( m_Label.size()>0 )
4497 m_TitleWidth = ClampText(Title, m_Font, (!m_IsMinimized)?(m_Width-5*m_Font->m_CharHeight):(16*m_Font->m_CharHeight));
4498 Gr->BuildText(m_TitleTextObj, &Title, NULL, NULL, 1, m_Font, 0, 0);
4500 if( !m_IsMinimized )
4503 vector<string> Labels;
4504 vector<color32> Colors;
4505 vector<color32> BgColors;
4506 bool HasBgColors = false;
4507 ListLabels(Labels, Colors, BgColors, &HasBgColors, m_Font, m_VarX1-m_VarX0, m_VarX2-m_VarX0);
4508 assert( Labels.size()==Colors.size() && Labels.size()==BgColors.size() );
4509 if( Labels.size()>0 )
4510 Gr->BuildText(m_LabelsTextObj, &(Labels[0]), &(Colors[0]), &(BgColors[0]), (int)Labels.size(), m_Font, m_LineSep, HasBgColors ? m_VarX1-m_VarX0-m_Font->m_CharHeight+2 : 0);
4512 Gr->BuildText(m_LabelsTextObj, NULL, NULL, NULL, 0, m_Font, m_LineSep, 0);
4514 // Should draw click button?
4515 m_DrawClickBtn = ( m_VarX2-m_VarX1>4*IncrBtnWidth(m_Font->m_CharHeight)
4516 && m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size()
4517 && m_HierTags[m_HighlightedLine].m_Var!=NULL
4518 && !m_HierTags[m_HighlightedLine].m_Var->IsGroup()
4519 && !static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly
4520 && ( static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BUTTON ));
4521 // || static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BOOLCPP
4522 // || static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BOOL8
4523 // || static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BOOL16
4524 // || static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BOOL32 ));
4526 // Should draw [-/+] button?
4527 m_DrawIncrDecrBtn = ( m_VarX2-m_VarX1>5*IncrBtnWidth(m_Font->m_CharHeight)
4528 && m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size()
4529 && m_HierTags[m_HighlightedLine].m_Var!=NULL
4530 && !m_HierTags[m_HighlightedLine].m_Var->IsGroup()
4531 && static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type!=TW_TYPE_BUTTON
4532 && !static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly
4533 && !static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_NoSlider
4534 && !(m_EditInPlace.m_Active && m_EditInPlace.m_Var==m_HierTags[m_HighlightedLine].m_Var) );
4536 // Should draw [v] button (list)?
4537 m_DrawListBtn = ( m_VarX2-m_VarX1>2*IncrBtnWidth(m_Font->m_CharHeight)
4538 && m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size()
4539 && m_HierTags[m_HighlightedLine].m_Var!=NULL
4540 && !m_HierTags[m_HighlightedLine].m_Var->IsGroup()
4541 && IsEnumType(static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type)
4542 && !static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly );
4544 // Should draw [<>] button (bool)?
4545 m_DrawBoolBtn = ( m_VarX2-m_VarX1>4*IncrBtnWidth(m_Font->m_CharHeight)
4546 && m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size()
4547 && m_HierTags[m_HighlightedLine].m_Var!=NULL
4548 && !m_HierTags[m_HighlightedLine].m_Var->IsGroup()
4549 && !static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly
4550 && ( static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BOOLCPP
4551 || static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BOOL8
4552 || static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BOOL16
4553 || static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BOOL32 ));
4555 // Should draw [o] button?
4556 m_DrawRotoBtn = m_DrawIncrDecrBtn;
4558 m_DrawRotoBtn = ( m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size()
4559 && m_HierTags[m_HighlightedLine].m_Var!=NULL
4560 && !m_HierTags[m_HighlightedLine].m_Var->IsGroup()
4561 && static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type!=TW_TYPE_BUTTON
4562 && !static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly
4563 && !static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_NoSlider );
4567 vector<string>& Values = Labels; // reuse
4571 ListValues(Values, Colors, BgColors, m_Font, m_VarX2-m_VarX1);
4572 assert( BgColors.size()==Values.size() && Colors.size()==Values.size() );
4573 if( Values.size()>0 )
4574 Gr->BuildText(m_ValuesTextObj, &(Values[0]), &(Colors[0]), &(BgColors[0]), (int)Values.size(), m_Font, m_LineSep, m_VarX2-m_VarX1);
4576 Gr->BuildText(m_ValuesTextObj, NULL, NULL, NULL, 0, m_Font, m_LineSep, m_VarX2-m_VarX1);
4578 // Build key shortcut text
4580 m_ShortcutLine = -1;
4581 if( m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size() && m_HierTags[m_HighlightedLine].m_Var!=NULL && !m_HierTags[m_HighlightedLine].m_Var->IsGroup() )
4583 const CTwVarAtom *Atom = static_cast<const CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var);
4584 if( Atom->m_KeyIncr[0]>0 || Atom->m_KeyDecr[0]>0 )
4586 if( Atom->m_KeyIncr[0]>0 && Atom->m_KeyDecr[0]>0 )
4587 Shortcut = "Keys: ";
4590 if( Atom->m_KeyIncr[0]>0 )
4591 TwGetKeyString(&Shortcut, Atom->m_KeyIncr[0], Atom->m_KeyIncr[1]);
4593 Shortcut += "(none)";
4594 if( Atom->m_KeyDecr[0]>0 )
4597 TwGetKeyString(&Shortcut, Atom->m_KeyDecr[0], Atom->m_KeyDecr[1]);
4599 m_ShortcutLine = m_HighlightedLine;
4602 ClampText(Shortcut, m_Font, m_Width-3*m_Font->m_CharHeight);
4603 Gr->BuildText(m_ShortcutTextObj, &Shortcut, NULL, NULL, 1, m_Font, 0, 0);
4605 // build headers text
4606 if (m_HighlightLabelsHeader || m_HighlightValuesHeader) {
4607 std::string HeadersText = "Fit column content";
4608 ClampText(HeadersText, m_Font, m_Width-3*m_Font->m_CharHeight);
4609 Gr->BuildText(m_HeadersTextObj, &HeadersText, NULL, NULL, 1, m_Font, 0, 0);
4617 m_LastUpdateTime = float(g_BarTimer.GetTime());
4620 // ---------------------------------------------------------------------------
4622 void CTwBar::DrawHierHandle()
4625 ITwGraph *Gr = g_TwMgr->m_Graph;
4627 //int x0 = m_PosX+m_Font->m_CharHeight+1;
4629 //int x2 = m_PosX+m_VarX0-5;
4630 //int x2 = m_PosX+3*m_Font->m_CharWidth[(int)' ']-2;
4631 int x2 = m_PosX+m_Font->m_CharHeight-3;
4638 int y0 = m_PosY+m_VarY0 +1;
4640 int dh0 = (m_Font->m_CharHeight+m_Sep-1-w)/2;
4646 if( !m_IsPopupList )
4649 int nh = (int)m_HierTags.size();
4650 for( h=0; h<nh; ++h )
4652 y1 = y0 + m_Font->m_CharHeight+m_Sep-1;
4653 if( m_HierTags[h].m_Var->IsGroup() )
4654 Grp = static_cast<CTwVarGroup *>(m_HierTags[h].m_Var);
4658 int dx = m_HierTags[h].m_Level * (x2-x0);
4662 if( m_ColGrpBg!=0 && Grp->m_StructValuePtr==NULL )
4664 color32 cb = (Grp->m_StructType==TW_TYPE_HELP_STRUCT) ? m_ColStructBg : m_ColGrpBg;
4665 //Gr->DrawRect(x0+dx-1, y0, m_PosX+m_VarX2, y0+m_Font->m_CharHeight-1, cb);
4666 Gr->DrawRect(x2+dx+3, y0, m_PosX+m_VarX2, y0+m_Font->m_CharHeight-1+m_LineSep-1, cb);
4671 Gr->DrawLine(dx+x2+1,y0+dh0+1, dx+x2+1,y0+dh1+1, m_ColLineShadow);
4672 Gr->DrawLine(dx+x0+1,y0+dh1+1, dx+x2+2,y0+dh1+1, m_ColLineShadow);
4675 //Gr->DrawRect(x0+1,y0+dh0+1,x2-1,y0+dh1-1, (h==m_HighlightedLine) ? m_ColHighBtn : m_ColBtn);
4676 Gr->DrawRect(dx+x0, y0+dh0, dx+x2, y0+dh1, (h==m_HighlightedLine) ? m_ColHighFold : m_ColFold);
4679 Gr->DrawLine(dx+x0,y0+dh0, dx+x2,y0+dh0, m_ColLine);
4680 Gr->DrawLine(dx+x2,y0+dh0, dx+x2,y0+dh1+1, m_ColLine);
4681 Gr->DrawLine(dx+x2,y0+dh1, dx+x0,y0+dh1, m_ColLine);
4682 Gr->DrawLine(dx+x0,y0+dh1, dx+x0,y0+dh0, m_ColLine);
4685 Gr->DrawLine(dx+x0+2,y0+dh0+w/2, dx+x2-1,y0+dh0+w/2, m_ColTitleText);
4687 Gr->DrawLine(dx+x1,y0+dh0+2, dx+x1,y0+dh1-1, m_ColTitleText);
4690 if( m_ColGrpBg!=0 && Grp->m_StructValuePtr==NULL )
4692 color32 cb = (Grp->m_StructType==TW_TYPE_HELP_STRUCT) ? m_ColStructBg : m_ColGrpBg;
4693 //int decal = m_Font->m_CharHeight/2-2+2*m_HierTags[h].m_Level;
4694 //if( decal>m_Font->m_CharHeight-3 )
4695 // decal = m_Font->m_CharHeight-3;
4696 int margin = dx; //m_Font->m_CharWidth[(int)' ']*m_HierTags[h].m_Level;
4697 //Gr->DrawRect(m_PosX+m_VarX0+margin, y0+decal, m_PosX+m_VarX2, y0+m_Font->m_CharHeight-1, cb);
4698 Gr->DrawRect(m_PosX+m_VarX0+margin-1, y0+1, m_PosX+m_VarX2, y0+m_Font->m_CharHeight, cb);// m_ColHierBg);
4699 //Gr->DrawRect(m_PosX+m_VarX0-4, y0+m_Font->m_CharHeight/2-1, m_PosX+m_VarX0+margin-2, y0+m_Font->m_CharHeight/2, m_ColHierBg);
4703 else if( static_cast<CTwVarAtom *>(m_HierTags[h].m_Var)->m_Type==TW_TYPE_HELP_GRP && m_ColHelpBg!=0 )
4704 Gr->DrawRect(m_PosX+m_VarX0+m_HierTags[h].m_Var->m_LeftMargin, y0+m_HierTags[h].m_Var->m_TopMargin, m_PosX+m_VarX2, y0+m_Font->m_CharHeight-1, m_ColHelpBg);
4705 //else if( static_cast<CTwVarAtom *>(m_HierTags[h].m_Var)->m_Type==TW_TYPE_HELP_HEADER && m_ColHelpBg!=0 )
4706 // Gr->DrawRect(m_PosX+m_VarX0+m_HierTags[h].m_Var->m_LeftMargin, y0+m_HierTags[h].m_Var->m_TopMargin, m_PosX+m_VarX2, y0+m_Font->m_CharHeight-1, m_ColHelpBg);
4708 else if( static_cast<CTwVarAtom *>(m_HierTags[h].m_Var)->m_Type==TW_TYPE_BUTTON && m_ColBtn!=0 )
4711 int cbx0 = m_PosX+m_VarX2-2*bw+bw/2, cby0 = y0+2, cbx1 = m_PosX+m_VarX2-2-bw/2, cby1 = y0+m_Font->m_CharHeight-4;
4712 if( m_HighlightClickBtn )
4714 Gr->DrawRect(cbx0+2, cby0+2, cbx1+2, cby1+2, m_ColBtn);
4715 Gr->DrawLine(cbx0+3, cby1+3, cbx1+4, cby1+3, 0x7F000000);
4716 Gr->DrawLine(cbx1+3, cby0+3, cbx1+3, cby1+3, 0x7F000000);
4720 Gr->DrawRect(cbx0+3, cby1+1, cbx1+3, cby1+3, 0x7F000000);
4721 Gr->DrawRect(cbx1+1, cby0+3, cbx1+3, cby1, 0x7F000000);
4722 Gr->DrawRect(cbx0, cby0, cbx1, cby1, m_ColBtn);
4731 if( m_NbDisplayedLines<m_NbHierLines )
4734 y0 = m_PosY+m_VarY0;
4735 y1 = m_PosY+m_VarY1;
4737 //x1 = m_PosX+m_Font->m_CharHeight-2;
4738 x0 = m_PosX + m_VarX2+4;
4739 x1 = x0 + m_Font->m_CharHeight-4;
4740 if( ((x0+x1)&1)==1 )
4745 Gr->DrawRect(x0+2,y0+w, x1-2,y1-1-w, (m_ColBg&0xffffff)|0x11000000);
4746 if( m_DrawHandles || m_IsPopupList )
4748 // scroll handle shadow lines
4749 Gr->DrawLine(x1-1,m_ScrollY0+1, x1-1,m_ScrollY1+1, m_ColLineShadow);
4750 Gr->DrawLine(x0+2,m_ScrollY1+1, x1,m_ScrollY1+1, m_ColLineShadow);
4753 for( i=0; i<(x1-x0-2)/2; ++i )
4755 Gr->DrawLine(x0+2+i,y0+w-2*i, x1-i,y0+w-2*i, m_ColLineShadow);
4756 Gr->DrawLine(x0+1+i,y0+w-1-2*i, x1-1-i,y0+w-1-2*i, m_HighlightUpScroll?((m_ColLine&0xffffff)|0x4f000000):m_ColLine);
4758 Gr->DrawLine(x0+2+i,y1-w+2+2*i, x1-i,y1-w+2+2*i, m_ColLineShadow);
4759 Gr->DrawLine(x0+1+i,y1-w+1+2*i, x1-1-i,y1-w+1+2*i, m_HighlightDnScroll?((m_ColLine&0xffffff)|0x4f000000):m_ColLine);
4763 Gr->DrawLine((x0+x1)/2-1,y0+w, (x0+x1)/2-1,m_ScrollY0, m_ColLine);
4764 Gr->DrawLine((x0+x1)/2,y0+w, (x0+x1)/2,m_ScrollY0, m_ColLine);
4765 Gr->DrawLine((x0+x1)/2+1,y0+w, (x0+x1)/2+1,m_ScrollY0, m_ColLineShadow);
4766 Gr->DrawLine((x0+x1)/2-1,m_ScrollY1, (x0+x1)/2-1,y1-w+1, m_ColLine);
4767 Gr->DrawLine((x0+x1)/2,m_ScrollY1, (x0+x1)/2,y1-w+1, m_ColLine);
4768 Gr->DrawLine((x0+x1)/2+1,m_ScrollY1, (x0+x1)/2+1,y1-w+1, m_ColLineShadow);
4769 // scroll handle lines
4770 Gr->DrawRect(x0+2,m_ScrollY0+1, x1-3,m_ScrollY1-1, m_HighlightScroll?m_ColHighBtn:m_ColBtn);
4771 Gr->DrawLine(x1-2,m_ScrollY0, x1-2,m_ScrollY1, m_ColLine);
4772 Gr->DrawLine(x0+1,m_ScrollY0, x0+1,m_ScrollY1, m_ColLine);
4773 Gr->DrawLine(x0+1,m_ScrollY1, x1-1,m_ScrollY1, m_ColLine);
4774 Gr->DrawLine(x0+1,m_ScrollY0, x1-2,m_ScrollY0, m_ColLine);
4777 Gr->DrawRect(x0+3,m_ScrollY0+1, x1-3,m_ScrollY1-1, m_ColBtn);
4780 if( m_DrawHandles && !m_IsPopupList )
4782 if( m_Resizable ) // Draw resize handles
4785 Gr->DrawLine(m_PosX+3, m_PosY+m_Height-m_Font->m_CharHeight+3, m_PosX+3, m_PosY+m_Height-4, m_ColLine);
4786 Gr->DrawLine(m_PosX+4, m_PosY+m_Height-m_Font->m_CharHeight+4, m_PosX+4, m_PosY+m_Height-3, m_ColLineShadow);
4787 Gr->DrawLine(m_PosX+3, m_PosY+m_Height-4, m_PosX+m_Font->m_CharHeight-4, m_PosY+m_Height-4, m_ColLine);
4788 Gr->DrawLine(m_PosX+4, m_PosY+m_Height-3, m_PosX+m_Font->m_CharHeight-3, m_PosY+m_Height-3, m_ColLineShadow);
4790 Gr->DrawLine(m_PosX+m_Width-4, m_PosY+m_Height-m_Font->m_CharHeight+3, m_PosX+m_Width-4, m_PosY+m_Height-4, m_ColLine);
4791 Gr->DrawLine(m_PosX+m_Width-3, m_PosY+m_Height-m_Font->m_CharHeight+4, m_PosX+m_Width-3, m_PosY+m_Height-3, m_ColLineShadow);
4792 Gr->DrawLine(m_PosX+m_Width-4, m_PosY+m_Height-4, m_PosX+m_Width-m_Font->m_CharHeight+3, m_PosY+m_Height-4, m_ColLine);
4793 Gr->DrawLine(m_PosX+m_Width-3, m_PosY+m_Height-3, m_PosX+m_Width-m_Font->m_CharHeight+4, m_PosY+m_Height-3, m_ColLineShadow);
4795 Gr->DrawLine(m_PosX+3, m_PosY+m_Font->m_CharHeight-4, m_PosX+3, m_PosY+3, m_ColLine);
4796 Gr->DrawLine(m_PosX+4, m_PosY+m_Font->m_CharHeight-3, m_PosX+4, m_PosY+4, m_ColLineShadow);
4797 Gr->DrawLine(m_PosX+3, m_PosY+3, m_PosX+m_Font->m_CharHeight-4, m_PosY+3, m_ColLine);
4798 Gr->DrawLine(m_PosX+4, m_PosY+4, m_PosX+m_Font->m_CharHeight-3, m_PosY+4, m_ColLineShadow);
4800 Gr->DrawLine(m_PosX+m_Width-4, m_PosY+3, m_PosX+m_Width-m_Font->m_CharHeight+3, m_PosY+3, m_ColLine);
4801 Gr->DrawLine(m_PosX+m_Width-3, m_PosY+4, m_PosX+m_Width-m_Font->m_CharHeight+4, m_PosY+4, m_ColLineShadow);
4802 Gr->DrawLine(m_PosX+m_Width-4, m_PosY+m_Font->m_CharHeight-4, m_PosX+m_Width-4, m_PosY+3, m_ColLine);
4803 Gr->DrawLine(m_PosX+m_Width-3, m_PosY+m_Font->m_CharHeight-3, m_PosX+m_Width-3, m_PosY+4, m_ColLineShadow);
4806 int xm = m_PosX+m_Width-2*m_Font->m_CharHeight, wm=m_Font->m_CharHeight-6;
4807 wm = (wm<6) ? 6 : wm;
4808 if( m_Iconifiable ) // Draw minimize button
4810 Gr->DrawRect(xm+1, m_PosY+4, xm+wm-1, m_PosY+3+wm, m_HighlightMinimize?m_ColHighBtn:((m_ColBtn&0xffffff)|0x4f000000));
4811 Gr->DrawLine(xm, m_PosY+3, xm+wm, m_PosY+3, m_ColLine);
4812 Gr->DrawLine(xm+wm, m_PosY+3, xm+wm, m_PosY+3+wm, m_ColLine);
4813 Gr->DrawLine(xm+wm, m_PosY+3+wm, xm, m_PosY+3+wm, m_ColLine);
4814 Gr->DrawLine(xm, m_PosY+3+wm, xm, m_PosY+3, m_ColLine);
4815 Gr->DrawLine(xm+wm+1, m_PosY+4, xm+wm+1, m_PosY+4+wm, m_ColLineShadow);
4816 Gr->DrawLine(xm+wm+1, m_PosY+4+wm, xm, m_PosY+4+wm, m_ColLineShadow);
4817 Gr->DrawLine(xm+wm/3+((wm<9)?1:0)-1, m_PosY+4+wm/3-((wm<9)?0:1), xm+wm/2, m_PosY+2+wm-1, m_ColTitleText, true);
4818 Gr->DrawLine(xm+wm-wm/3+((wm<9)?0:1), m_PosY+4+wm/3-((wm<9)?0:1), xm+wm/2, m_PosY+2+wm-1, m_ColTitleText, true);
4821 if( g_TwMgr->m_FontResizable ) // Draw font button
4823 xm = m_PosX+m_Font->m_CharHeight+2;
4824 Gr->DrawRect(xm+1, m_PosY+4, xm+wm-1, m_PosY+3+wm, m_HighlightFont?m_ColHighBtn:((m_ColBtn&0xffffff)|0x4f000000));
4825 Gr->DrawLine(xm, m_PosY+3, xm+wm, m_PosY+3, m_ColLine);
4826 Gr->DrawLine(xm+wm, m_PosY+3, xm+wm, m_PosY+3+wm, m_ColLine);
4827 Gr->DrawLine(xm+wm, m_PosY+3+wm, xm, m_PosY+3+wm, m_ColLine);
4828 Gr->DrawLine(xm, m_PosY+3+wm, xm, m_PosY+3, m_ColLine);
4829 Gr->DrawLine(xm+wm+1, m_PosY+4, xm+wm+1, m_PosY+4+wm, m_ColLineShadow);
4830 Gr->DrawLine(xm+wm+1, m_PosY+4+wm, xm, m_PosY+4+wm, m_ColLineShadow);
4831 Gr->DrawLine(xm+wm/2-wm/6, m_PosY+3+wm/3, xm+wm/2+wm/6+1, m_PosY+3+wm/3, m_ColTitleText);
4832 Gr->DrawLine(xm+wm/2-wm/6, m_PosY+3+wm/3, xm+wm/2-wm/6, m_PosY+4+wm-wm/3+(wm>11?1:0), m_ColTitleText);
4833 Gr->DrawLine(xm+wm/2-wm/6, m_PosY+3+wm/2+(wm>11?1:0), xm+wm/2+wm/6, m_PosY+3+wm/2+(wm>11?1:0), m_ColTitleText);
4838 // ---------------------------------------------------------------------------
4840 void CTwBar::Draw(int _DrawPart)
4842 PERF( PerfTimer Timer; double DT; )
4845 ITwGraph *Gr = g_TwMgr->m_Graph;
4847 m_CustomRecords.clear();
4849 if( float(g_BarTimer.GetTime())>m_LastUpdateTime+m_UpdatePeriod )
4852 if( m_HighlightedLine!=m_HighlightedLinePrev )
4854 m_HighlightedLinePrev = m_HighlightedLine;
4858 if( m_IsHelpBar && g_TwMgr->m_HelpBarNotUpToDate )
4859 g_TwMgr->UpdateHelpBar();
4864 if( !m_IsMinimized )
4867 int LevelSpace = max(m_Font->m_CharHeight-6, 4); // space used by DrawHierHandles
4869 color32 colBg = m_ColBg, colBg1 = m_ColBg1, colBg2 = m_ColBg2;
4870 if( m_DrawHandles || m_IsPopupList )
4872 unsigned int alphaMin = 0x70;
4875 if( (colBg>>24)<alphaMin )
4876 colBg = (colBg&0xffffff)|(alphaMin<<24);
4877 if( (colBg1>>24)<alphaMin )
4878 colBg1 = (colBg1&0xffffff)|(alphaMin<<24);
4879 if( (colBg2>>24)<alphaMin )
4880 colBg2 = (colBg2&0xffffff)|(alphaMin<<24);
4884 if( !m_IsPopupList )
4886 PERF( Timer.Reset(); )
4887 if( _DrawPart&DRAW_BG )
4889 //Gr->DrawRect(m_PosX, m_PosY, m_PosX+m_Width-1, m_PosY+m_Font->m_CharHeight+1, (m_HighlightTitle||m_MouseDragTitle) ? m_ColTitleHighBg : (m_DrawHandles ? m_ColTitleBg : m_ColTitleUnactiveBg));
4890 if( m_HighlightTitle || m_MouseDragTitle )
4891 Gr->DrawRect(m_PosX, m_PosY, m_PosX+m_Width-1, m_PosY+m_Font->m_CharHeight+1, m_ColTitleHighBg);
4892 else if (m_DrawHandles)
4893 Gr->DrawRect(m_PosX, m_PosY, m_PosX+m_Width-1, m_PosY+m_Font->m_CharHeight+1, m_ColTitleBg, m_ColTitleBg, colBg2, colBg1);
4895 Gr->DrawRect(m_PosX, m_PosY, m_PosX+m_Width-1, m_PosY+m_Font->m_CharHeight+1, m_ColTitleBg, m_ColTitleBg, colBg2, colBg1);
4897 if( _DrawPart&DRAW_CONTENT )
4899 const color32 COL0 = 0x50ffffff;
4900 const color32 COL1 = 0x501f1f1f;
4901 Gr->DrawRect(m_PosX, m_PosY, m_PosX+m_Width-1, y, COL0, COL0, COL1, COL1);
4902 if( m_ColTitleShadow!=0 )
4903 Gr->DrawText(m_TitleTextObj, m_PosX+(m_Width-m_TitleWidth)/2+1, m_PosY+1, m_ColTitleShadow, 0);
4904 Gr->DrawText(m_TitleTextObj, m_PosX+(m_Width-m_TitleWidth)/2, m_PosY, m_ColTitleText, 0);
4906 y = m_PosY+m_Font->m_CharHeight+1;
4907 if( _DrawPart&DRAW_CONTENT && m_DrawHandles )
4908 Gr->DrawLine(m_PosX, y, m_PosX+m_Width-1, y, 0x30ffffff); // 0x80afafaf);
4910 PERF( DT = Timer.GetTime(); printf("Title=%.4fms ", 1000.0*DT); )
4914 PERF( Timer.Reset(); )
4915 if( _DrawPart&DRAW_BG )
4917 Gr->DrawRect(m_PosX, y, m_PosX+m_Width-1, m_PosY+m_Height-1, colBg2, colBg1, colBg1, colBg);
4918 //Gr->DrawRect(m_PosX, y, m_PosX+m_VarX0-5, m_PosY+m_Height-1, m_ColHierBg);
4919 Gr->DrawRect(m_PosX+m_VarX2+3, y, m_PosX+m_Width-1, m_PosY+m_Height-1, m_ColHierBg);
4922 if( _DrawPart&DRAW_CONTENT )
4924 // Draw highlighted line
4925 if( m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size() && m_HierTags[m_HighlightedLine].m_Var!=NULL
4926 && (m_HierTags[m_HighlightedLine].m_Var->IsGroup()
4927 || (!static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly && !m_IsHelpBar
4928 && !m_HierTags[m_HighlightedLine].m_Var->IsCustom() ) ) ) // !(static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type>=TW_TYPE_CUSTOM_BASE && static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type<TW_TYPE_CUSTOM_BASE+(int)g_TwMgr->m_Customs.size()))) )
4930 int y0 = m_PosY + m_VarY0 + m_HighlightedLine*(m_Font->m_CharHeight+m_LineSep);
4931 Gr->DrawRect(m_PosX+LevelSpace+6+LevelSpace*m_HierTags[m_HighlightedLine].m_Level, y0+1, m_PosX+m_VarX2, y0+m_Font->m_CharHeight-1+m_LineSep-1, m_ColHighBg0, m_ColHighBg0, m_ColHighBg1, m_ColHighBg1);
4932 int eps = (g_TwMgr->m_GraphAPI==TW_OPENGL || g_TwMgr->m_GraphAPI==TW_OPENGL_CORE) ? 1 : 0;
4933 if( !m_EditInPlace.m_Active )
4934 Gr->DrawLine(m_PosX+LevelSpace+6+LevelSpace*m_HierTags[m_HighlightedLine].m_Level, y0+m_Font->m_CharHeight+m_LineSep-1+eps, m_PosX+m_VarX2, y0+m_Font->m_CharHeight+m_LineSep-1+eps, m_ColUnderline);
4936 else if( m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size() && !m_HierTags[m_HighlightedLine].m_Var->IsGroup() )
4938 int y0 = m_PosY + m_VarY0 + m_HighlightedLine*(m_Font->m_CharHeight+m_LineSep);
4939 color32 col = ColorBlend(m_ColHighBg0, m_ColHighBg1, 0.5f);
4940 CTwVarAtom *Atom = static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var);
4941 if( !Atom->IsCustom() // !(Atom->m_Type>=TW_TYPE_CUSTOM_BASE && Atom->m_Type<TW_TYPE_CUSTOM_BASE+(int)g_TwMgr->m_Customs.size())
4942 && !(Atom->m_Type==TW_TYPE_BUTTON && Atom->m_Val.m_Button.m_Callback==NULL) )
4943 Gr->DrawRect(m_PosX+LevelSpace+6+LevelSpace*m_HierTags[m_HighlightedLine].m_Level, y0+1, m_PosX+m_VarX2, y0+m_Font->m_CharHeight-1+m_LineSep-1, col);
4945 Gr->DrawRect(m_PosX+LevelSpace+6+LevelSpace*m_HierTags[m_HighlightedLine].m_Level, y0+1, m_PosX+LevelSpace+6+LevelSpace*m_HierTags[m_HighlightedLine].m_Level+4, y0+m_Font->m_CharHeight-1+m_LineSep-1, col);
4947 color32 clight = 0x5FFFFFFF; // bar contour
4948 Gr->DrawLine(m_PosX, m_PosY, m_PosX, m_PosY+m_Height, clight);
4949 Gr->DrawLine(m_PosX, m_PosY, m_PosX+m_Width, m_PosY, clight);
4950 Gr->DrawLine(m_PosX+m_Width, m_PosY, m_PosX+m_Width, m_PosY+m_Height, clight);
4951 Gr->DrawLine(m_PosX, m_PosY+m_Height, m_PosX+m_Width, m_PosY+m_Height, clight);
4952 int dshad = 3; // bar shadows
4953 color32 cshad = (((m_Color>>24)/2)<<24) & 0xFF000000;
4954 Gr->DrawRect(m_PosX, m_PosY+m_Height, m_PosX+dshad, m_PosY+m_Height+dshad, 0, cshad, 0, 0);
4955 Gr->DrawRect(m_PosX+dshad+1, m_PosY+m_Height, m_PosX+m_Width-1, m_PosY+m_Height+dshad, cshad, cshad, 0, 0);
4956 Gr->DrawRect(m_PosX+m_Width, m_PosY+m_Height, m_PosX+m_Width+dshad, m_PosY+m_Height+dshad, cshad, 0, 0, 0);
4957 Gr->DrawRect(m_PosX+m_Width, m_PosY, m_PosX+m_Width+dshad, m_PosY+dshad, 0, 0, cshad, 0);
4958 Gr->DrawRect(m_PosX+m_Width, m_PosY+dshad+1, m_PosX+m_Width+dshad, m_PosY+m_Height-1, cshad, 0, cshad, 0);
4959 PERF( DT = Timer.GetTime(); printf("Bg=%.4fms ", 1000.0*DT); )
4961 // Draw hierarchy handle
4962 PERF( Timer.Reset(); )
4964 PERF( DT = Timer.GetTime(); printf("Handles=%.4fms ", 1000.0*DT); )
4967 PERF( Timer.Reset(); )
4968 Gr->DrawText(m_LabelsTextObj, m_PosX+LevelSpace+6, m_PosY+m_VarY0, 0 /*m_ColLabelText*/, 0);
4969 PERF( DT = Timer.GetTime(); printf("Labels=%.4fms ", 1000.0*DT); )
4972 if( !m_IsPopupList )
4974 PERF( Timer.Reset(); )
4975 Gr->DrawText(m_ValuesTextObj, m_PosX+m_VarX1, m_PosY+m_VarY0, 0 /*m_ColValText*/, 0 /*m_ColValBg*/);
4976 PERF( DT = Timer.GetTime(); printf("Values=%.4fms ", 1000.0*DT); )
4979 // Draw preview for color values and draw buttons and custom types
4980 int h, nh = (int)m_HierTags.size();
4981 int yh = m_PosY+m_VarY0;
4982 int bw = IncrBtnWidth(m_Font->m_CharHeight);
4983 for( h=0; h<nh; ++h )
4985 if( m_HierTags[h].m_Var->IsGroup() )
4987 const CTwVarGroup * Grp = static_cast<const CTwVarGroup *>(m_HierTags[h].m_Var);
4988 if( Grp->m_SummaryCallback==CColorExt::SummaryCB && Grp->m_StructValuePtr!=NULL )
4991 if( Grp->m_Vars.size()>0 && Grp->m_Vars[0]!=NULL && !Grp->m_Vars[0]->IsGroup() )
4992 static_cast<CTwVarAtom *>(Grp->m_Vars[0])->ValueToDouble(); // force ext update
4993 int ydecal = (g_TwMgr->m_GraphAPI==TW_OPENGL || g_TwMgr->m_GraphAPI==TW_OPENGL_CORE) ? 1 : 0;
4994 const int checker = 8;
4995 for( int c=0; c<checker; ++c )
4996 Gr->DrawRect(m_PosX+m_VarX1+(c*(m_VarX2-m_VarX1))/checker, yh+1+ydecal+((c%2)*(m_Font->m_CharHeight-2))/2, m_PosX+m_VarX1-1+((c+1)*(m_VarX2-m_VarX1))/checker, yh+ydecal+(((c%2)+1)*(m_Font->m_CharHeight-2))/2, 0xffffffff);
4997 Gr->DrawRect(m_PosX+m_VarX1, yh+1+ydecal, m_PosX+m_VarX2-1, yh+ydecal+m_Font->m_CharHeight-2, 0xbfffffff);
4998 const CColorExt *colExt = static_cast<const CColorExt *>(Grp->m_StructValuePtr);
4999 color32 col = Color32FromARGBi((colExt->m_HasAlpha ? colExt->A : 255), colExt->R, colExt->G, colExt->B);
5001 Gr->DrawRect(m_PosX+m_VarX1, yh+1+ydecal, m_PosX+m_VarX2-1, yh+ydecal+m_Font->m_CharHeight-2, col);
5003 Gr->DrawLine(m_PosX+m_VarX1-1, yh, m_PosX+m_VarX2+1, yh, 0xff000000);
5004 Gr->DrawLine(m_PosX+m_VarX1-1, yh+m_Font->m_CharHeight, m_PosX+m_VarX2+1, yh+m_Font->m_CharHeight, 0xff000000);
5005 Gr->DrawLine(m_PosX+m_VarX1-1, yh, m_PosX+m_VarX1-1, yh+m_Font->m_CharHeight, 0xff000000);
5006 Gr->DrawLine(m_PosX+m_VarX2, yh, m_PosX+m_VarX2, yh+m_Font->m_CharHeight, 0xff000000);
5009 //else if( Grp->m_SummaryCallback==CustomTypeSummaryCB && Grp->m_StructValuePtr!=NULL )
5013 else if( static_cast<CTwVarAtom *>(m_HierTags[h].m_Var)->m_Type==TW_TYPE_BUTTON && !m_IsPopupList )
5017 if( m_ButtonAlign == BUTTON_ALIGN_LEFT )
5019 cbx0 = m_PosX+m_VarX1+2;
5020 cbx1 = m_PosX+m_VarX1+bw;
5022 else if( m_ButtonAlign == BUTTON_ALIGN_CENTER )
5024 cbx0 = m_PosX+(m_VarX1+m_VarX2)/2-bw/2+1;
5025 cbx1 = m_PosX+(m_VarX1+m_VarX2)/2+bw/2-1;
5029 cbx0 = m_PosX+m_VarX2-2*bw+bw/2;
5030 cbx1 = m_PosX+m_VarX2-2-bw/2;
5033 int cby1 = yh+m_Font->m_CharHeight-3;
5034 if( !static_cast<CTwVarAtom *>(m_HierTags[h].m_Var)->m_ReadOnly )
5036 double BtnAutoDelta = g_TwMgr->m_Timer.GetTime() - m_HighlightClickBtnAuto;
5037 if( (m_HighlightClickBtn || (BtnAutoDelta>=0 && BtnAutoDelta<0.1)) && h==m_HighlightedLine )
5039 cbx0--; cby0--; cbx1--; cby1--;
5040 Gr->DrawRect(cbx0+2, cby0+2, cbx1+2, cby1+2, m_ColHighBtn);
5041 Gr->DrawLine(cbx0+3, cby1+3, cbx1+4, cby1+3, 0xAF000000);
5042 Gr->DrawLine(cbx1+3, cby0+3, cbx1+3, cby1+3, 0xAF000000);
5043 Gr->DrawLine(cbx0+2, cby0+2, cbx0+2, cby1+2, m_ColLine);
5044 Gr->DrawLine(cbx0+2, cby1+2, cbx1+2, cby1+2, m_ColLine);
5045 Gr->DrawLine(cbx1+2, cby1+2, cbx1+2, cby0+2, m_ColLine);
5046 Gr->DrawLine(cbx1+2, cby0+2, cbx0+2, cby0+2, m_ColLine);
5050 Gr->DrawRect(cbx0+2, cby1+1, cbx1+2, cby1+2, (h==m_HighlightedLine)?0xAF000000:0x7F000000);
5051 Gr->DrawRect(cbx1+1, cby0+2, cbx1+2, cby1, (h==m_HighlightedLine)?0xAF000000:0x7F000000);
5052 Gr->DrawRect(cbx0, cby0, cbx1, cby1, (h==m_HighlightedLine)?m_ColHighBtn:m_ColBtn);
5053 Gr->DrawLine(cbx0, cby0, cbx0, cby1, m_ColLine);
5054 Gr->DrawLine(cbx0, cby1, cbx1, cby1, m_ColLine);
5055 Gr->DrawLine(cbx1, cby1, cbx1, cby0, m_ColLine);
5056 Gr->DrawLine(cbx1, cby0, cbx0, cby0, m_ColLine);
5059 else if( static_cast<CTwVarAtom *>(m_HierTags[h].m_Var)->m_Val.m_Button.m_Callback!=NULL )
5061 Gr->DrawRect(cbx0+1, cby0+1, cbx1+1, cby1+1, m_ColBtn);
5063 else if( static_cast<CTwVarAtom *>(m_HierTags[h].m_Var)->m_Val.m_Button.m_Separator==1 )
5065 int LevelSpace = max(m_Font->m_CharHeight-6, 4); // space used by DrawHierHandles
5066 Gr->DrawLine(m_PosX+m_VarX0+m_HierTags[h].m_Level*LevelSpace, yh+m_Font->m_CharHeight/2, m_PosX+m_VarX2, yh+m_Font->m_CharHeight/2, m_ColSeparator );
5069 else if( m_HierTags[h].m_Var->IsCustom() ) //static_cast<CTwVarAtom *>(m_HierTags[h].m_Var)->m_Type>=TW_TYPE_CUSTOM_BASE && static_cast<CTwVarAtom *>(m_HierTags[h].m_Var)->m_Type<TW_TYPE_CUSTOM_BASE+(int)g_TwMgr->m_Customs.size() )
5070 { // record custom types
5071 CTwMgr::CMemberProxy *mProxy = static_cast<CTwVarAtom *>(m_HierTags[h].m_Var)->m_Val.m_Custom.m_MemberProxy;
5072 if( mProxy!=NULL && mProxy->m_StructProxy!=NULL )
5074 CustomMap::iterator it = m_CustomRecords.find(mProxy->m_StructProxy);
5075 int xMin = m_PosX + m_VarX0 + m_HierTags[h].m_Level*LevelSpace;
5076 int xMax = m_PosX + m_VarX2 - 2;
5078 int yMax = yh + m_Font->m_CharHeight;
5079 if( it==m_CustomRecords.end() )
5081 std::pair<CTwMgr::CStructProxy*, CCustomRecord> pr;
5082 pr.first = mProxy->m_StructProxy;
5083 pr.second.m_IndexMin = pr.second.m_IndexMax = mProxy->m_MemberIndex;
5084 pr.second.m_XMin = xMin;
5085 pr.second.m_XMax = xMax;
5086 pr.second.m_YMin = yMin;
5087 pr.second.m_YMax = yMax;
5088 pr.second.m_Y0 = 0; // will be filled by the draw loop below
5089 pr.second.m_Y1 = 0; // will be filled by the draw loop below
5090 pr.second.m_Var = mProxy->m_VarParent;
5091 m_CustomRecords.insert(pr);
5095 it->second.m_IndexMin = min(it->second.m_IndexMin, mProxy->m_MemberIndex);
5096 it->second.m_IndexMax = min(it->second.m_IndexMax, mProxy->m_MemberIndex);
5097 it->second.m_XMin = min(it->second.m_XMin, xMin);
5098 it->second.m_XMax = max(it->second.m_XMax, xMax);
5099 it->second.m_YMin = min(it->second.m_YMin, yMin);
5100 it->second.m_YMax = max(it->second.m_YMax, yMax);
5101 it->second.m_Y0 = 0;
5102 it->second.m_Y1 = 0;
5103 assert( it->second.m_Var==mProxy->m_VarParent );
5108 yh += m_Font->m_CharHeight+m_LineSep;
5111 // Draw custom types
5112 for( CustomMap::iterator it = m_CustomRecords.begin(); it!=m_CustomRecords.end(); ++it )
5114 CTwMgr::CStructProxy *sProxy = it->first;
5115 assert( sProxy!=NULL );
5116 CCustomRecord& r = it->second;
5117 if( sProxy->m_CustomDrawCallback!=NULL )
5119 int y0 = r.m_YMin - max(r.m_IndexMin - sProxy->m_CustomIndexFirst, 0)*(m_Font->m_CharHeight + m_LineSep);
5120 int y1 = y0 + max(sProxy->m_CustomIndexLast - sProxy->m_CustomIndexFirst + 1, 0)*(m_Font->m_CharHeight + m_LineSep) - 2;
5125 Gr->ChangeViewport(r.m_XMin, r.m_YMin, r.m_XMax-r.m_XMin+1, r.m_YMax-r.m_YMin+1, 0, y0-r.m_YMin+1);
5126 sProxy->m_CustomDrawCallback(r.m_XMax-r.m_XMin, y1-y0, sProxy->m_StructExtData, sProxy->m_StructClientData, this, r.m_Var);
5127 Gr->RestoreViewport();
5132 if( m_DrawHandles && !m_IsPopupList )
5134 // Draw -/+/o/click/v buttons
5135 if( (m_DrawIncrDecrBtn || m_DrawClickBtn || m_DrawListBtn || m_DrawBoolBtn || m_DrawRotoBtn) && m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size() )
5137 int y0 = m_PosY + m_VarY0 + m_HighlightedLine*(m_Font->m_CharHeight+m_LineSep);
5138 if( m_DrawIncrDecrBtn )
5142 if( !m_HierTags[m_HighlightedLine].m_Var->IsGroup() )
5144 const CTwVarAtom *Atom = static_cast<const CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var);
5145 double v, vmin, vmax;
5146 v = Atom->ValueToDouble();
5147 Atom->MinMaxStepToDouble(&vmin, &vmax, NULL);
5153 Gr->DrawRect(m_PosX+m_VarX2-2*bw+1, y0+1, m_PosX+m_VarX2-bw-1, y0+m_Font->m_CharHeight-2, (m_HighlightDecrBtn && !IsMin)?m_ColHighBtn:m_ColBtn);
5154 Gr->DrawRect(m_PosX+m_VarX2-bw+1, y0+1, m_PosX+m_VarX2-1, y0+m_Font->m_CharHeight-2, (m_HighlightIncrBtn && !IsMax)?m_ColHighBtn:m_ColBtn);
5156 Gr->DrawLine(m_PosX+m_VarX2-2*bw+3+(bw>8?1:0), y0+m_Font->m_CharHeight/2, m_PosX+m_VarX2-bw-2-(bw>8?1:0), y0+m_Font->m_CharHeight/2, IsMin?m_ColValTextRO:m_ColTitleText);
5158 Gr->DrawLine(m_PosX+m_VarX2-bw+3, y0+m_Font->m_CharHeight/2, m_PosX+m_VarX2-2, y0+m_Font->m_CharHeight/2, IsMax?m_ColValTextRO:m_ColTitleText);
5159 Gr->DrawLine(m_PosX+m_VarX2-bw/2, y0+m_Font->m_CharHeight/2-bw/2+2, m_PosX+m_VarX2-bw/2, y0+m_Font->m_CharHeight/2+bw/2-1, IsMax?m_ColValTextRO:m_ColTitleText);
5161 Gr->DrawRect(m_PosX+m_VarX2-3*bw+1, y0+1, m_PosX+m_VarX2-2*bw-1, y0+m_Font->m_CharHeight-2, (m_HighlightDecrBtn && !IsMin)?m_ColHighBtn:m_ColBtn);
5162 Gr->DrawRect(m_PosX+m_VarX2-2*bw+1, y0+1, m_PosX+m_VarX2-bw-1, y0+m_Font->m_CharHeight-2, (m_HighlightIncrBtn && !IsMax)?m_ColHighBtn:m_ColBtn);
5164 Gr->DrawLine(m_PosX+m_VarX2-3*bw+3+(bw>8?1:0), y0+m_Font->m_CharHeight/2, m_PosX+m_VarX2-2*bw-2-(bw>8?1:0), y0+m_Font->m_CharHeight/2, IsMin?m_ColValTextRO:m_ColTitleText);
5166 Gr->DrawLine(m_PosX+m_VarX2-2*bw+3, y0+m_Font->m_CharHeight/2, m_PosX+m_VarX2-bw-2, y0+m_Font->m_CharHeight/2, IsMax?m_ColValTextRO:m_ColTitleText);
5167 Gr->DrawLine(m_PosX+m_VarX2-bw-bw/2, y0+m_Font->m_CharHeight/2-bw/2+2, m_PosX+m_VarX2-bw-bw/2, y0+m_Font->m_CharHeight/2+bw/2-1, IsMax?m_ColValTextRO:m_ColTitleText);
5169 else if( m_DrawListBtn )
5174 Gr->DrawRect(m_PosX+m_VarX2-bw+1, y0+1, m_PosX+m_VarX2-1, y0+m_Font->m_CharHeight-2, m_HighlightListBtn?m_ColHighBtn:m_ColBtn);
5175 Gr->DrawLine(m_PosX+m_VarX2-bw+4+dx, y0+m_Font->m_CharHeight/2-eps, m_PosX+m_VarX2-bw/2+1+dx, y0+m_Font->m_CharHeight-4, m_ColTitleText, true);
5176 Gr->DrawLine(m_PosX+m_VarX2-bw/2+1+dx, y0+m_Font->m_CharHeight-4, m_PosX+m_VarX2-2+dx, y0+m_Font->m_CharHeight/2-1, m_ColTitleText, true);
5178 else if( m_DrawBoolBtn )
5180 Gr->DrawRect(m_PosX+m_VarX2-bw+1, y0+1, m_PosX+m_VarX2-1, y0+m_Font->m_CharHeight-2, m_HighlightBoolBtn?m_ColHighBtn:m_ColBtn);
5182 //Gr->DrawLine(m_PosX+m_VarX2-bw/2-bw/6, y0+m_Font->m_CharHeight/2-bw/6, m_PosX+m_VarX2-bw/2+bw/6, y0+m_Font->m_CharHeight/2+bw/6, m_ColTitleText, true);
5183 //Gr->DrawLine(m_PosX+m_VarX2-bw/2-bw/6, y0+m_Font->m_CharHeight/2+bw/6, m_PosX+m_VarX2-bw/2+bw/6, y0+m_Font->m_CharHeight/2-bw/6, m_ColTitleText, true);
5187 Gr->DrawLine(m_PosX+m_VarX2-bw/2-1, y0+m_Font->m_CharHeight/2-s, m_PosX+m_VarX2-bw/2-s-1, y0+m_Font->m_CharHeight/2, m_ColTitleText, true);
5188 Gr->DrawLine(m_PosX+m_VarX2-bw/2-s-1, y0+m_Font->m_CharHeight/2, m_PosX+m_VarX2-bw/2-eps, y0+m_Font->m_CharHeight/2+s+1-eps, m_ColTitleText, true);
5189 //Gr->DrawLine(m_PosX+m_VarX2-bw/2+1, y0+m_Font->m_CharHeight/2+s, m_PosX+m_VarX2-bw/2+s+1, y0+m_Font->m_CharHeight/2, m_ColTitleText, true);
5190 //Gr->DrawLine(m_PosX+m_VarX2-bw/2+s+1, y0+m_Font->m_CharHeight/2, m_PosX+m_VarX2-bw/2+1, y0+m_Font->m_CharHeight/2-s, m_ColTitleText, true);
5191 Gr->DrawLine(m_PosX+m_VarX2-bw/2+2, y0+m_Font->m_CharHeight/2-s, m_PosX+m_VarX2-bw/2+s+2, y0+m_Font->m_CharHeight/2, m_ColTitleText, true);
5192 Gr->DrawLine(m_PosX+m_VarX2-bw/2+s+2, y0+m_Font->m_CharHeight/2, m_PosX+m_VarX2-bw/2+1+eps, y0+m_Font->m_CharHeight/2+s+1-eps, m_ColTitleText, true);
5197 // [o] rotoslider button
5199 Gr->DrawRect(m_PosX+m_VarX1-bw-1, y0+1, m_PosX+m_VarX1-3, y0+m_Font->m_CharHeight-2, m_HighlightRotoBtn?m_ColHighBtn:m_ColBtn);
5200 Gr->DrawLine(m_PosX+m_VarX1-bw+bw/2-2, y0+m_Font->m_CharHeight/2-1, m_PosX+m_VarX1-bw+bw/2-1, y0+m_Font->m_CharHeight/2-1, m_ColTitleText);
5201 Gr->DrawLine(m_PosX+m_VarX1-bw+bw/2-3, y0+m_Font->m_CharHeight/2+0, m_PosX+m_VarX1-bw+bw/2+0, y0+m_Font->m_CharHeight/2+0, m_ColTitleText);
5202 Gr->DrawLine(m_PosX+m_VarX1-bw+bw/2-3, y0+m_Font->m_CharHeight/2+1, m_PosX+m_VarX1-bw+bw/2+0, y0+m_Font->m_CharHeight/2+1, m_ColTitleText);
5203 Gr->DrawLine(m_PosX+m_VarX1-bw+bw/2-2, y0+m_Font->m_CharHeight/2+2, m_PosX+m_VarX1-bw+bw/2-1, y0+m_Font->m_CharHeight/2+2, m_ColTitleText);
5206 Gr->DrawRect(m_PosX+m_VarX2-3*bw+1, y0+1, m_PosX+m_VarX2-2*bw-1, y0+m_Font->m_CharHeight-2, m_HighlightRotoBtn?m_ColHighBtn:m_ColBtn);
5207 Gr->DrawLine(m_PosX+m_VarX2-3*bw+bw/2+0, y0+m_Font->m_CharHeight/2-1, m_PosX+m_VarX2-3*bw+bw/2+1, y0+m_Font->m_CharHeight/2-1, m_ColTitleText);
5208 Gr->DrawLine(m_PosX+m_VarX2-3*bw+bw/2-1, y0+m_Font->m_CharHeight/2+0, m_PosX+m_VarX2-3*bw+bw/2+2, y0+m_Font->m_CharHeight/2+0, m_ColTitleText);
5209 Gr->DrawLine(m_PosX+m_VarX2-3*bw+bw/2-1, y0+m_Font->m_CharHeight/2+1, m_PosX+m_VarX2-3*bw+bw/2+2, y0+m_Font->m_CharHeight/2+1, m_ColTitleText);
5210 Gr->DrawLine(m_PosX+m_VarX2-3*bw+bw/2+0, y0+m_Font->m_CharHeight/2+2, m_PosX+m_VarX2-3*bw+bw/2+1, y0+m_Font->m_CharHeight/2+2, m_ColTitleText);
5213 Gr->DrawRect(m_PosX+m_VarX2-bw+1, y0+1, m_PosX+m_VarX2-1, y0+m_Font->m_CharHeight-2, m_HighlightRotoBtn?m_ColHighBtn:m_ColBtn);
5214 Gr->DrawLine(m_PosX+m_VarX2-bw+bw/2+0, y0+m_Font->m_CharHeight/2-1+dy, m_PosX+m_VarX2-bw+bw/2+1, y0+m_Font->m_CharHeight/2-1+dy, m_ColTitleText, true);
5215 Gr->DrawLine(m_PosX+m_VarX2-bw+bw/2-1, y0+m_Font->m_CharHeight/2+0+dy, m_PosX+m_VarX2-bw+bw/2+2, y0+m_Font->m_CharHeight/2+0+dy, m_ColTitleText, true);
5216 Gr->DrawLine(m_PosX+m_VarX2-bw+bw/2-1, y0+m_Font->m_CharHeight/2+1+dy, m_PosX+m_VarX2-bw+bw/2+2, y0+m_Font->m_CharHeight/2+1+dy, m_ColTitleText, true);
5217 Gr->DrawLine(m_PosX+m_VarX2-bw+bw/2+0, y0+m_Font->m_CharHeight/2+2+dy, m_PosX+m_VarX2-bw+bw/2+1, y0+m_Font->m_CharHeight/2+2+dy, m_ColTitleText, true);
5222 // Draw value width slider
5223 if( !m_HighlightValWidth )
5225 color32 col = m_DarkText ? COLOR32_WHITE : m_ColTitleText;
5226 Gr->DrawRect(m_PosX+m_VarX1-2, m_PosY+m_VarY0-8, m_PosX+m_VarX1-1, m_PosY+m_VarY0-4, col);
5227 Gr->DrawLine(m_PosX+m_VarX1-1, m_PosY+m_VarY0-3, m_PosX+m_VarX1, m_PosY+m_VarY0-3, m_ColLineShadow);
5228 Gr->DrawLine(m_PosX+m_VarX1, m_PosY+m_VarY0-3, m_PosX+m_VarX1, m_PosY+m_VarY0-8, m_ColLineShadow);
5232 color32 col = m_DarkText ? COLOR32_WHITE : m_ColTitleText;
5233 Gr->DrawRect(m_PosX+m_VarX1-2, m_PosY+m_VarY0-8, m_PosX+m_VarX1-1, m_PosY+m_VarY1, col);
5234 Gr->DrawLine(m_PosX+m_VarX1-1, m_PosY+m_VarY1+1, m_PosX+m_VarX1, m_PosY+m_VarY1+1, m_ColLineShadow);
5235 Gr->DrawLine(m_PosX+m_VarX1, m_PosY+m_VarY1+1, m_PosX+m_VarX1, m_PosY+m_VarY0-8, m_ColLineShadow);
5238 // Draw labels & values headers
5239 if (m_HighlightLabelsHeader)
5241 Gr->DrawRect(m_PosX+m_VarX0, m_PosY+m_Font->m_CharHeight+2, m_PosX+m_VarX1-4, m_PosY+m_VarY0-1, m_ColHighBg0, m_ColHighBg0, m_ColHighBg1, m_ColHighBg1);
5243 if (m_HighlightValuesHeader)
5245 Gr->DrawRect(m_PosX+m_VarX1+2, m_PosY+m_Font->m_CharHeight+2, m_PosX+m_VarX2, m_PosY+m_VarY0-1, m_ColHighBg0, m_ColHighBg0, m_ColHighBg1, m_ColHighBg1);
5249 // Draw key shortcut text
5250 if( m_HighlightedLine>=0 && m_HighlightedLine==m_ShortcutLine && !m_IsPopupList && !m_EditInPlace.m_Active )
5252 PERF( Timer.Reset(); )
5253 Gr->DrawRect(m_PosX+m_Font->m_CharHeight-2, m_PosY+m_VarY1+1, m_PosX+m_Width-m_Font->m_CharHeight-2, m_PosY+m_VarY1+1+m_Font->m_CharHeight, m_ColShortcutBg);
5254 Gr->DrawText(m_ShortcutTextObj, m_PosX+m_Font->m_CharHeight, m_PosY+m_VarY1+1, m_ColShortcutText, 0);
5255 PERF( DT = Timer.GetTime(); printf("Shortcut=%.4fms ", 1000.0*DT); )
5257 else if( (m_HighlightLabelsHeader || m_HighlightValuesHeader) && !m_IsPopupList && !m_EditInPlace.m_Active )
5259 Gr->DrawRect(m_PosX+m_Font->m_CharHeight-2, m_PosY+m_VarY1+1, m_PosX+m_Width-m_Font->m_CharHeight-2, m_PosY+m_VarY1+1+m_Font->m_CharHeight, m_ColShortcutBg);
5260 Gr->DrawText(m_HeadersTextObj, m_PosX+m_Font->m_CharHeight, m_PosY+m_VarY1+1, m_ColShortcutText, 0);
5262 else if( m_IsHelpBar )
5264 if( g_TwMgr->m_KeyPressedTextObj && g_TwMgr->m_KeyPressedStr.size()>0 ) // Draw key pressed
5266 if( g_TwMgr->m_KeyPressedBuildText )
5268 string Str = g_TwMgr->m_KeyPressedStr;
5269 ClampText(Str, m_Font, m_Width-2*m_Font->m_CharHeight);
5270 g_TwMgr->m_Graph->BuildText(g_TwMgr->m_KeyPressedTextObj, &Str, NULL, NULL, 1, g_TwMgr->m_HelpBar->m_Font, 0, 0);
5271 g_TwMgr->m_KeyPressedBuildText = false;
5272 g_TwMgr->m_KeyPressedTime = (float)g_BarTimer.GetTime();
5274 if( (float)g_BarTimer.GetTime()>g_TwMgr->m_KeyPressedTime+1.0f ) // draw key pressed at least 1 second
5275 g_TwMgr->m_KeyPressedStr = "";
5276 PERF( Timer.Reset(); )
5277 Gr->DrawRect(m_PosX+m_Font->m_CharHeight-2, m_PosY+m_VarY1+1, m_PosX+m_Width-m_Font->m_CharHeight-2, m_PosY+m_VarY1+1+m_Font->m_CharHeight, m_ColShortcutBg);
5278 Gr->DrawText(g_TwMgr->m_KeyPressedTextObj, m_PosX+m_Font->m_CharHeight, m_PosY+m_VarY1+1, m_ColShortcutText, 0);
5279 PERF( DT = Timer.GetTime(); printf("KeyPressed=%.4fms ", 1000.0*DT); )
5283 if( g_TwMgr->m_InfoBuildText )
5285 string Info = "> AntTweakBar";
5287 sprintf(Ver, " (v%d.%02d)", TW_VERSION/100, TW_VERSION%100);
5289 ClampText(Info, m_Font, m_Width-2*m_Font->m_CharHeight);
5290 g_TwMgr->m_Graph->BuildText(g_TwMgr->m_InfoTextObj, &Info, NULL, NULL, 1, g_TwMgr->m_HelpBar->m_Font, 0, 0);
5291 g_TwMgr->m_InfoBuildText = false;
5293 PERF( Timer.Reset(); )
5294 Gr->DrawRect(m_PosX+m_Font->m_CharHeight-2, m_PosY+m_VarY1+1, m_PosX+m_Width-m_Font->m_CharHeight-2, m_PosY+m_VarY1+1+m_Font->m_CharHeight, m_ColShortcutBg);
5295 Gr->DrawText(g_TwMgr->m_InfoTextObj, m_PosX+m_Font->m_CharHeight, m_PosY+m_VarY1+1, m_ColInfoText, 0);
5296 PERF( DT = Timer.GetTime(); printf("Info=%.4fms ", 1000.0*DT); )
5300 if( !m_IsPopupList )
5309 if( g_TwMgr->m_PopupBar!=NULL && this!=g_TwMgr->m_PopupBar )
5311 // darken bar if a popup bar is displayed
5312 Gr->DrawRect(m_PosX, m_PosY, m_PosX+m_Width-1, m_PosY+m_Height-1, 0x1F000000);
5318 int vpx, vpy, vpw, vph;
5321 vpw = g_TwMgr->m_WndWidth;
5322 vph = g_TwMgr->m_WndHeight;
5323 if( g_TwMgr->m_IconMarginX>0 )
5325 vpx = min(g_TwMgr->m_IconMarginX, vpw/3);
5328 if( g_TwMgr->m_IconMarginY>0 )
5330 vpy = min(g_TwMgr->m_IconMarginY, vph/3);
5334 int MinXOffset = 0, MinYOffset = 0;
5335 if( g_TwMgr->m_IconPos==3 ) // top-right
5337 if( g_TwMgr->m_IconAlign==1 ) // horizontal
5339 int n = max(1, vpw/m_Font->m_CharHeight-1);
5340 m_MinPosX = vpx + vpw-((m_MinNumber%n)+1)*m_Font->m_CharHeight;
5341 m_MinPosY = vpy + (m_MinNumber/n)*m_Font->m_CharHeight;
5342 MinYOffset = m_Font->m_CharHeight;
5343 MinXOffset = -m_TitleWidth;
5347 int n = max(1, vph/m_Font->m_CharHeight-1);
5348 m_MinPosY = vpy + (m_MinNumber%n)*m_Font->m_CharHeight;
5349 m_MinPosX = vpx + vpw-((m_MinNumber/n)+1)*m_Font->m_CharHeight;
5350 MinXOffset = -m_TitleWidth-m_Font->m_CharHeight;
5353 else if( g_TwMgr->m_IconPos==2 ) // top-left
5355 if( g_TwMgr->m_IconAlign==1 ) // horizontal
5357 int n = max(1, vpw/m_Font->m_CharHeight-1);
5358 m_MinPosX = vpx + (m_MinNumber%n)*m_Font->m_CharHeight;
5359 m_MinPosY = vpy + (m_MinNumber/n)*m_Font->m_CharHeight;
5360 MinYOffset = m_Font->m_CharHeight;
5364 int n = max(1, vph/m_Font->m_CharHeight-1);
5365 m_MinPosY = vpy + (m_MinNumber%n)*m_Font->m_CharHeight;
5366 m_MinPosX = vpx + (m_MinNumber/n)*m_Font->m_CharHeight;
5367 MinXOffset = m_Font->m_CharHeight;
5370 else if( g_TwMgr->m_IconPos==1 ) // bottom-right
5372 if( g_TwMgr->m_IconAlign==1 ) // horizontal
5374 int n = max(1, vpw/m_Font->m_CharHeight-1);
5375 m_MinPosX = vpx + vpw-((m_MinNumber%n)+1)*m_Font->m_CharHeight;
5376 m_MinPosY = vpy + vph-((m_MinNumber/n)+1)*m_Font->m_CharHeight;
5377 MinYOffset = -m_Font->m_CharHeight;
5378 MinXOffset = -m_TitleWidth;
5382 int n = max(1, vph/m_Font->m_CharHeight-1);
5383 m_MinPosY = vpy + vph-((m_MinNumber%n)+1)*m_Font->m_CharHeight;
5384 m_MinPosX = vpx + vpw-((m_MinNumber/n)+1)*m_Font->m_CharHeight;
5385 MinXOffset = -m_TitleWidth-m_Font->m_CharHeight;
5390 if( g_TwMgr->m_IconAlign==1 ) // horizontal
5392 int n = max(1, vpw/m_Font->m_CharHeight-1);
5393 m_MinPosX = vpx + (m_MinNumber%n)*m_Font->m_CharHeight;
5394 m_MinPosY = vpy + vph-((m_MinNumber/n)+1)*m_Font->m_CharHeight;
5395 MinYOffset = -m_Font->m_CharHeight;
5399 int n = max(1, vph/m_Font->m_CharHeight-1);
5400 m_MinPosY = vpy + vph-((m_MinNumber%n)+1)*m_Font->m_CharHeight;
5401 m_MinPosX = vpx + (m_MinNumber/n)*m_Font->m_CharHeight;
5402 MinXOffset = m_Font->m_CharHeight;
5406 if( m_HighlightMaximize )
5409 if( _DrawPart&DRAW_BG )
5411 Gr->DrawRect(m_MinPosX, m_MinPosY, m_MinPosX+m_Font->m_CharHeight, m_MinPosY+m_Font->m_CharHeight, m_ColTitleUnactiveBg);
5412 Gr->DrawRect(m_MinPosX+MinXOffset, m_MinPosY+MinYOffset, m_MinPosX+MinXOffset+m_TitleWidth+m_Font->m_CharHeight, m_MinPosY+MinYOffset+m_Font->m_CharHeight, m_ColTitleUnactiveBg);
5414 if( _DrawPart&DRAW_CONTENT )
5416 if( m_ColTitleShadow!=0 )
5417 Gr->DrawText(m_TitleTextObj, m_MinPosX+MinXOffset+m_Font->m_CharHeight/2, m_MinPosY+1+MinYOffset, m_ColTitleShadow, 0);
5418 Gr->DrawText(m_TitleTextObj, m_MinPosX+MinXOffset+m_Font->m_CharHeight/2, m_MinPosY+MinYOffset, m_ColTitleText, 0);
5424 // Draw maximize button
5425 int xm = m_MinPosX+2, wm=m_Font->m_CharHeight-6;
5426 wm = (wm<6) ? 6 : wm;
5427 if( _DrawPart&DRAW_BG )
5428 Gr->DrawRect(xm+1, m_MinPosY+4, xm+wm-1, m_MinPosY+3+wm, m_HighlightMaximize?m_ColHighBtn:m_ColBtn);
5429 if( _DrawPart&DRAW_CONTENT )
5431 Gr->DrawLine(xm, m_MinPosY+3, xm+wm, m_MinPosY+3, m_ColLine);
5432 Gr->DrawLine(xm+wm, m_MinPosY+3, xm+wm, m_MinPosY+3+wm, m_ColLine);
5433 Gr->DrawLine(xm+wm, m_MinPosY+3+wm, xm, m_MinPosY+3+wm, m_ColLine);
5434 Gr->DrawLine(xm, m_MinPosY+3+wm, xm, m_MinPosY+3, m_ColLine);
5435 Gr->DrawLine(xm+wm+1, m_MinPosY+4, xm+wm+1, m_MinPosY+4+wm, m_ColLineShadow);
5436 Gr->DrawLine(xm+wm+1, m_MinPosY+4+wm, xm, m_MinPosY+4+wm, m_ColLineShadow);
5437 Gr->DrawLine(xm+wm/3-1, m_MinPosY+3+wm-wm/3, xm+wm/2, m_MinPosY+6, m_ColTitleText, true);
5438 Gr->DrawLine(xm+wm-wm/3+1, m_MinPosY+3+wm-wm/3, xm+wm/2, m_MinPosY+6, m_ColTitleText, true);
5444 int xm = m_MinPosX+2, wm=m_Font->m_CharHeight-6;
5445 wm = (wm<6) ? 6 : wm;
5446 if( _DrawPart&DRAW_BG )
5447 Gr->DrawRect(xm+1, m_MinPosY+4, xm+wm-1, m_MinPosY+3+wm, m_HighlightMaximize?m_ColHighBtn:m_ColBtn);
5448 if( _DrawPart&DRAW_CONTENT )
5450 Gr->DrawLine(xm, m_MinPosY+3, xm+wm, m_MinPosY+3, m_ColLine);
5451 Gr->DrawLine(xm+wm, m_MinPosY+3, xm+wm, m_MinPosY+3+wm, m_ColLine);
5452 Gr->DrawLine(xm+wm, m_MinPosY+3+wm, xm, m_MinPosY+3+wm, m_ColLine);
5453 Gr->DrawLine(xm, m_MinPosY+3+wm, xm, m_MinPosY+3, m_ColLine);
5454 Gr->DrawLine(xm+wm+1, m_MinPosY+4, xm+wm+1, m_MinPosY+4+wm, m_ColLineShadow);
5455 Gr->DrawLine(xm+wm+1, m_MinPosY+4+wm, xm, m_MinPosY+4+wm, m_ColLineShadow);
5456 Gr->DrawLine(xm+wm/2-wm/6, m_MinPosY+3+wm/4, xm+wm-wm/3, m_MinPosY+3+wm/4, m_ColTitleText);
5457 Gr->DrawLine(xm+wm-wm/3, m_MinPosY+3+wm/4, xm+wm-wm/3, m_MinPosY+3+wm/2, m_ColTitleText);
5458 Gr->DrawLine(xm+wm-wm/3, m_MinPosY+3+wm/2, xm+wm/2, m_MinPosY+3+wm/2, m_ColTitleText);
5459 Gr->DrawLine(xm+wm/2, m_MinPosY+3+wm/2, xm+wm/2, m_MinPosY+3+wm-wm/4, m_ColTitleText);
5460 Gr->DrawLine(xm+wm/2, m_MinPosY+3+wm-wm/4+1, xm+wm/2, m_MinPosY+3+wm-wm/4+2, m_ColTitleText);
5466 // ---------------------------------------------------------------------------
5468 bool CTwBar::MouseMotion(int _X, int _Y)
5470 assert(g_TwMgr->m_Graph && g_TwMgr->m_WndHeight>0 && g_TwMgr->m_WndWidth>0);
5474 bool Handled = false;
5475 bool CustomArea = false;
5476 if( !m_IsMinimized )
5478 bool InBar = (_X>=m_PosX && _X<m_PosX+m_Width && _Y>=m_PosY && _Y<m_PosY+m_Height);
5479 for( size_t ib=0; ib<g_TwMgr->m_Bars.size(); ++ib )
5480 if( g_TwMgr->m_Bars[ib]!=NULL )
5482 g_TwMgr->m_Bars[ib]->m_DrawHandles = false;
5483 g_TwMgr->m_Bars[ib]->m_HighlightTitle = false;
5485 m_DrawHandles = InBar;
5486 const int ContainedMargin = 32;
5491 m_HighlightedLine = -1;
5492 m_HighlightIncrBtn = false;
5493 m_HighlightDecrBtn = false;
5494 m_HighlightRotoBtn = false;
5495 if( abs(m_MouseOriginX-_X)>6 || abs(m_MouseOriginY-_Y)>6 )
5496 m_HighlightClickBtn = false;
5497 m_HighlightListBtn = false;
5498 m_HighlightTitle = false;
5499 m_HighlightScroll = false;
5500 m_HighlightUpScroll = false;
5501 m_HighlightDnScroll = false;
5502 m_HighlightMinimize = false;
5503 m_HighlightFont = false;
5504 m_HighlightValWidth = false;
5505 m_HighlightLabelsHeader = false;
5506 m_HighlightValuesHeader = false;
5507 //if( InBar && _X>m_PosX+m_Font->m_CharHeight+1 && _X<m_PosX+m_VarX2 && _Y>=m_PosY+m_VarY0 && _Y<m_PosY+m_VarY1 )
5508 if( InBar && _X>m_PosX+2 && _X<m_PosX+m_VarX2 && _Y>=m_PosY+m_VarY0 && _Y<m_PosY+m_VarY1 )
5509 { // mouse over var line
5510 m_HighlightedLine = (_Y-m_PosY-m_VarY0)/(m_Font->m_CharHeight+m_LineSep);
5511 if( m_HighlightedLine>=(int)m_HierTags.size() )
5512 m_HighlightedLine = -1;
5513 else if(m_HighlightedLine>=0)
5514 m_HighlightedLineLastValid = m_HighlightedLine;
5515 if( m_HighlightedLine<0 || m_HierTags[m_HighlightedLine].m_Var==NULL || m_HierTags[m_HighlightedLine].m_Var->IsGroup() )
5516 ANT_SET_CURSOR(Arrow);
5519 if( !m_HierTags[m_HighlightedLine].m_Var->IsGroup() && static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_NoSlider )
5521 if( static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly && !m_IsHelpBar
5522 && !(static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Type==TW_TYPE_BUTTON && static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_Val.m_Button.m_Callback==NULL) )
5523 ANT_SET_CURSOR(No); //(Arrow);
5526 ANT_SET_CURSOR(Arrow);
5532 m_HighlightListBtn = true;
5537 m_HighlightBoolBtn = true;
5541 else if( m_DrawRotoBtn && ( _X>=m_PosX+m_VarX2-IncrBtnWidth(m_Font->m_CharHeight) || _X<m_PosX+m_VarX1 ) ) // [o] button
5542 //else if( m_DrawRotoBtn && _X<m_PosX+m_VarX1 ) // [o] button
5544 m_HighlightRotoBtn = true;
5545 ANT_SET_CURSOR(Point);
5547 else if( m_DrawIncrDecrBtn && _X>=m_PosX+m_VarX2-2*IncrBtnWidth(m_Font->m_CharHeight) ) // [+] button
5549 m_HighlightIncrBtn = true;
5550 ANT_SET_CURSOR(Arrow);
5552 else if( m_DrawIncrDecrBtn && _X>=m_PosX+m_VarX2-3*IncrBtnWidth(m_Font->m_CharHeight) ) // [-] button
5554 m_HighlightDecrBtn = true;
5555 ANT_SET_CURSOR(Arrow);
5557 else if( !m_HierTags[m_HighlightedLine].m_Var->IsGroup() && static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly )
5562 ANT_SET_CURSOR(Arrow);
5565 //ANT_SET_CURSOR(Point);
5566 ANT_SET_CURSOR(IBeam);
5569 else if( InBar && m_Movable && !m_IsPopupList && _X>=m_PosX+2*m_Font->m_CharHeight && _X<m_PosX+m_Width-2*m_Font->m_CharHeight && _Y<m_PosY+m_Font->m_CharHeight )
5570 { // mouse over title
5571 m_HighlightTitle = true;
5572 ANT_SET_CURSOR(Move);
5574 else if ( InBar && !m_IsPopupList && _X>=m_PosX+m_VarX1-5 && _X<m_PosX+m_VarX1+5 && _Y>m_PosY+m_Font->m_CharHeight && _Y<m_PosY+m_VarY0 )
5575 { // mouse over ValuesWidth handle
5576 m_HighlightValWidth = true;
5579 else if ( InBar && !m_IsPopupList && !m_IsHelpBar && _X>=m_PosX+m_VarX0 && _X<m_PosX+m_VarX1-5 && _Y>m_PosY+m_Font->m_CharHeight && _Y<m_PosY+m_VarY0 )
5580 { // mouse over left column header
5581 m_HighlightLabelsHeader = true;
5582 ANT_SET_CURSOR(Arrow);
5584 else if ( InBar && !m_IsPopupList && _X>=m_PosX+m_VarX1+5 && _X<m_PosX+m_VarX2 && _Y>m_PosY+m_Font->m_CharHeight && _Y<m_PosY+m_VarY0 )
5585 { // mouse over right column header
5586 m_HighlightValuesHeader = true;
5587 ANT_SET_CURSOR(Arrow);
5589 //else if( InBar && m_NbDisplayedLines<m_NbHierLines && _X>=m_PosX && _X<m_PosX+m_Font->m_CharHeight && _Y>=m_ScrollY0 && _Y<m_ScrollY1 )
5590 else if( InBar && m_NbDisplayedLines<m_NbHierLines && _X>=m_PosX+m_VarX2+2 && _X<m_PosX+m_Width-2 && _Y>=m_ScrollY0 && _Y<m_ScrollY1 )
5592 m_HighlightScroll = true;
5596 ANT_SET_CURSOR(Arrow);
5599 else if( InBar && _X>=m_PosX+m_VarX2+2 && _X<m_PosX+m_Width-2 && _Y>=m_PosY+m_VarY0 && _Y<m_ScrollY0 )
5601 m_HighlightUpScroll = true;
5602 ANT_SET_CURSOR(Arrow);
5604 else if( InBar && _X>=m_PosX+m_VarX2+2 && _X<m_PosX+m_Width-2 && _Y>=m_ScrollY1 && _Y<m_PosY+m_VarY1 )
5606 m_HighlightDnScroll = true;
5607 ANT_SET_CURSOR(Arrow);
5609 else if( InBar && m_Resizable && !m_IsPopupList && _X>=m_PosX && _X<m_PosX+m_Font->m_CharHeight && _Y>=m_PosY && _Y<m_PosY+m_Font->m_CharHeight )
5610 ANT_SET_CURSOR(TopLeft);
5611 else if( InBar && !m_IsPopupList && _X>=m_PosX && _X<m_PosX+m_Font->m_CharHeight && _Y>=m_PosY+m_Height-m_Font->m_CharHeight && _Y<m_PosY+m_Height )
5612 ANT_SET_CURSOR(BottomLeft);
5613 else if( InBar && m_Resizable && !m_IsPopupList && _X>=m_PosX+m_Width-m_Font->m_CharHeight && _X<m_PosX+m_Width && _Y>=m_PosY && _Y<m_PosY+m_Font->m_CharHeight )
5614 ANT_SET_CURSOR(TopRight);
5615 else if( InBar && m_Resizable && !m_IsPopupList && _X>=m_PosX+m_Width-m_Font->m_CharHeight && _X<m_PosX+m_Width && _Y>=m_PosY+m_Height-m_Font->m_CharHeight && _Y<m_PosY+m_Height )
5616 ANT_SET_CURSOR(BottomRight);
5617 else if( InBar && g_TwMgr->m_FontResizable && !m_IsPopupList && _X>=m_PosX+m_Font->m_CharHeight && _X<m_PosX+2*m_Font->m_CharHeight && _Y<m_PosY+m_Font->m_CharHeight )
5619 m_HighlightFont = true;
5620 ANT_SET_CURSOR(Arrow);
5622 else if( InBar && m_Iconifiable && !m_IsPopupList && _X>=m_PosX+m_Width-2*m_Font->m_CharHeight && _X<m_PosX+m_Width-m_Font->m_CharHeight && _Y<m_PosY+m_Font->m_CharHeight )
5624 m_HighlightMinimize = true;
5625 ANT_SET_CURSOR(Arrow);
5627 else if( m_IsHelpBar && InBar && _X>=m_PosX+m_VarX0 && _X<m_PosX+m_Width-m_Font->m_CharHeight && _Y>m_PosY+m_Height-m_Font->m_CharHeight && _Y<m_PosY+m_Height )
5628 ANT_SET_CURSOR(Arrow); //(Hand); // web link
5630 ANT_SET_CURSOR(Arrow);
5634 if( m_MouseDragVar && m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size() && m_HierTags[m_HighlightedLine].m_Var && !m_HierTags[m_HighlightedLine].m_Var->IsGroup() )
5637 CTwVarAtom *Var = static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var);
5638 int Delta = _X-m_MouseOriginX;
5641 if( !Var->m_NoSlider && !Var->m_ReadOnly )
5643 Var->Increment(Delta);
5646 m_VarHasBeenIncr = true;
5648 m_MouseOriginX = _X;
5649 m_MouseOriginY = _Y;
5650 if( !Var->m_NoSlider && !Var->m_ReadOnly )
5651 ANT_SET_CURSOR(Center);
5652 //ANT_SET_CURSOR(WE);
5654 ANT_SET_CURSOR(Arrow);
5659 if( !static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_NoSlider )
5660 RotoOnMouseMove(_X, _Y);
5662 if( static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly )
5664 else if( static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_NoSlider )
5666 ANT_SET_CURSOR(Arrow);
5669 m_VarHasBeenIncr = true;
5671 m_DrawHandles = true;
5673 else if( m_MouseDragTitle )
5676 m_PosX += _X-m_MouseOriginX;
5677 m_PosY += _Y-m_MouseOriginY;
5678 m_MouseOriginX = _X;
5679 m_MouseOriginY = _Y;
5680 int vpx, vpy, vpw, vph;
5683 vpw = g_TwMgr->m_WndWidth;
5684 vph = g_TwMgr->m_WndHeight;
5687 if( m_PosX+m_Width>vpx+vpw )
5688 m_PosX = vpx+vpw-m_Width;
5691 if( m_PosY+m_Height>vpy+vph )
5692 m_PosY = vpy+vph-m_Height;
5698 if( m_PosX+ContainedMargin>vpx+vpw )
5699 m_PosX = vpx+vpw-ContainedMargin;
5700 if( m_PosX+m_Width<vpx+ContainedMargin )
5701 m_PosX = vpx+ContainedMargin-m_Width;
5702 if( m_PosY+ContainedMargin>vpy+vph )
5703 m_PosY = vpy+vph-ContainedMargin;
5704 if( m_PosY+m_Height<vpy+ContainedMargin )
5705 m_PosY = vpy+ContainedMargin-m_Height;
5707 m_ScrollY0 += m_PosY-y;
5708 m_ScrollY1 += m_PosY-y;
5709 ANT_SET_CURSOR(Move);
5712 else if( m_MouseDragValWidth )
5714 m_ValuesWidth += m_MouseOriginX-_X;
5715 m_MouseOriginX = _X;
5718 g_TwMgr->m_HelpBarNotUpToDate = true;
5721 m_DrawHandles = true;
5723 else if( m_MouseDragScroll )
5727 int dl = ((_Y-m_MouseOriginY)*m_NbHierLines)/m_ScrollYH;
5728 if( m_FirstLine0+dl<0 )
5730 else if( m_FirstLine0+dl+m_NbDisplayedLines>m_NbHierLines )
5731 m_FirstLine = m_NbHierLines-m_NbDisplayedLines;
5733 m_FirstLine = m_FirstLine0+dl;
5739 ANT_SET_CURSOR(Arrow);
5742 m_DrawHandles = true;
5744 else if( m_MouseDragResizeUL )
5748 m_PosX += _X-m_MouseOriginX;
5749 m_PosY += _Y-m_MouseOriginY;
5750 m_Width -= _X-m_MouseOriginX;
5751 m_Height -= _Y-m_MouseOriginY;
5752 m_MouseOriginX = _X;
5753 m_MouseOriginY = _Y;
5754 int vpx = 0, vpy = 0, vpw = g_TwMgr->m_WndWidth, vph = g_TwMgr->m_WndHeight;
5757 if( m_PosX+ContainedMargin>vpx+vpw )
5758 m_PosX = vpx+vpw-ContainedMargin;
5759 if( m_PosX+m_Width<vpx+ContainedMargin )
5760 m_PosX = vpx+ContainedMargin-m_Width;
5761 if( m_PosY+ContainedMargin>vpy+vph )
5762 m_PosY = vpy+vph-ContainedMargin;
5763 if( m_PosY+m_Height<vpy+ContainedMargin )
5764 m_PosY = vpy+ContainedMargin-m_Height;
5779 if (m_ValuesWidthRatio > 0)
5780 m_ValuesWidth = int(m_ValuesWidthRatio * m_Width + 0.5);
5781 ANT_SET_CURSOR(TopLeft);
5785 g_TwMgr->m_HelpBarNotUpToDate = true;
5786 g_TwMgr->m_HelpBarUpdateNow = true;
5788 g_TwMgr->m_KeyPressedBuildText = true;
5789 g_TwMgr->m_InfoBuildText = true;
5791 m_DrawHandles = true;
5793 else if( m_MouseDragResizeUR )
5796 m_PosY += _Y-m_MouseOriginY;
5797 m_Width += _X-m_MouseOriginX;
5798 m_Height -= _Y-m_MouseOriginY;
5799 m_MouseOriginX = _X;
5800 m_MouseOriginY = _Y;
5801 int vpx = 0, vpy = 0, vpw = g_TwMgr->m_WndWidth, vph = g_TwMgr->m_WndHeight;
5804 if( m_PosX+ContainedMargin>vpx+vpw )
5805 m_PosX = vpx+vpw-ContainedMargin;
5806 if( m_PosX+m_Width<vpx+ContainedMargin )
5807 m_PosX = vpx+ContainedMargin-m_Width;
5808 if( m_PosY+ContainedMargin>vpy+vph )
5809 m_PosY = vpy+vph-ContainedMargin;
5810 if( m_PosY+m_Height<vpy+ContainedMargin )
5811 m_PosY = vpy+ContainedMargin-m_Height;
5815 if( m_PosX+m_Width>vpx+vpw )
5816 m_Width = vpx+vpw-m_PosX;
5823 if (m_ValuesWidthRatio > 0)
5824 m_ValuesWidth = int(m_ValuesWidthRatio * m_Width + 0.5);
5825 ANT_SET_CURSOR(TopRight);
5829 g_TwMgr->m_HelpBarNotUpToDate = true;
5830 g_TwMgr->m_HelpBarUpdateNow = true;
5832 g_TwMgr->m_KeyPressedBuildText = true;
5833 g_TwMgr->m_InfoBuildText = true;
5835 m_DrawHandles = true;
5837 else if( m_MouseDragResizeLL )
5840 m_PosX += _X-m_MouseOriginX;
5841 m_Width -= _X-m_MouseOriginX;
5842 m_Height += _Y-m_MouseOriginY;
5843 m_MouseOriginX = _X;
5844 m_MouseOriginY = _Y;
5845 int vpx = 0, vpy = 0, vpw = g_TwMgr->m_WndWidth, vph = g_TwMgr->m_WndHeight;
5848 if( m_PosX+ContainedMargin>vpx+vpw )
5849 m_PosX = vpx+vpw-ContainedMargin;
5850 if( m_PosX+m_Width<vpx+ContainedMargin )
5851 m_PosX = vpx+ContainedMargin-m_Width;
5852 if( m_PosY+ContainedMargin>vpy+vph )
5853 m_PosY = vpy+vph-ContainedMargin;
5854 if( m_PosY+m_Height<vpy+ContainedMargin )
5855 m_PosY = vpy+ContainedMargin-m_Height;
5859 if( m_PosY+m_Height>vpy+vph )
5860 m_Height = vpy+vph-m_PosY;
5867 if (m_ValuesWidthRatio > 0)
5868 m_ValuesWidth = int(m_ValuesWidthRatio * m_Width + 0.5);
5869 ANT_SET_CURSOR(BottomLeft);
5873 g_TwMgr->m_HelpBarNotUpToDate = true;
5874 g_TwMgr->m_HelpBarUpdateNow = true;
5876 g_TwMgr->m_KeyPressedBuildText = true;
5877 g_TwMgr->m_InfoBuildText = true;
5879 m_DrawHandles = true;
5881 else if( m_MouseDragResizeLR )
5883 m_Width += _X-m_MouseOriginX;
5884 m_Height += _Y-m_MouseOriginY;
5885 m_MouseOriginX = _X;
5886 m_MouseOriginY = _Y;
5887 int vpx = 0, vpy = 0, vpw = g_TwMgr->m_WndWidth, vph = g_TwMgr->m_WndHeight;
5890 if( m_PosX+ContainedMargin>vpx+vpw )
5891 m_PosX = vpx+vpw-ContainedMargin;
5892 if( m_PosX+m_Width<vpx+ContainedMargin )
5893 m_PosX = vpx+ContainedMargin-m_Width;
5894 if( m_PosY+ContainedMargin>vpy+vph )
5895 m_PosY = vpy+vph-ContainedMargin;
5896 if( m_PosY+m_Height<vpy+ContainedMargin )
5897 m_PosY = vpy+ContainedMargin-m_Height;
5901 if( m_PosX+m_Width>vpx+vpw )
5902 m_Width = vpx+vpw-m_PosX;
5903 if( m_PosY+m_Height>vpy+vph )
5904 m_Height = vpy+vph-m_PosY;
5906 if (m_ValuesWidthRatio > 0)
5907 m_ValuesWidth = int(m_ValuesWidthRatio * m_Width + 0.5);
5908 ANT_SET_CURSOR(BottomRight);
5912 g_TwMgr->m_HelpBarNotUpToDate = true;
5913 g_TwMgr->m_HelpBarUpdateNow = true;
5915 g_TwMgr->m_KeyPressedBuildText = true;
5916 g_TwMgr->m_InfoBuildText = true;
5918 m_DrawHandles = true;
5920 else if( m_EditInPlace.m_Active )
5922 EditInPlaceMouseMove(_X, _Y, true);
5923 ANT_SET_CURSOR(IBeam);
5927 // ANT_SET_CURSOR(Arrow);
5932 if( m_Iconifiable && _X>=m_MinPosX+2 && _X<m_MinPosX+m_Font->m_CharHeight && _Y>m_MinPosY && _Y<m_MinPosY+m_Font->m_CharHeight-2 )
5934 m_HighlightMaximize = true;
5936 ANT_SET_CURSOR(Arrow);
5939 ANT_SET_CURSOR(Help);
5941 ANT_SET_CURSOR(Arrow);
5946 m_HighlightMaximize = false;
5949 // Handled by a custom widget?
5950 CTwMgr::CStructProxy *currentCustomActiveStructProxy = NULL;
5951 if( g_TwMgr!=NULL && (!Handled || CustomArea) && !m_IsMinimized && m_CustomRecords.size()>0 )
5953 bool CustomHandled = false;
5954 for( int s=0; s<2; ++s ) // 2 iterations: first for custom widget having focus, second for others if no focused widget.
5955 for( CustomMap::iterator it=m_CustomRecords.begin(); it!=m_CustomRecords.end(); ++it )
5957 CTwMgr::CStructProxy *sProxy = it->first;
5958 const CCustomRecord& r = it->second;
5959 if( (s==1 || sProxy->m_CustomCaptureFocus) && !CustomHandled && sProxy!=NULL && sProxy->m_CustomMouseMotionCallback!=NULL && r.m_XMin<r.m_XMax && r.m_Y0<r.m_Y1 && r.m_YMin<=r.m_YMax && r.m_YMin>=r.m_Y0 && r.m_YMax<=r.m_Y1 )
5961 if( sProxy->m_CustomCaptureFocus || (_X>=r.m_XMin && _X<r.m_XMax && _Y>=r.m_YMin && _Y<r.m_YMax) )
5963 CustomHandled = sProxy->m_CustomMouseMotionCallback(_X-r.m_XMin, _Y-r.m_Y0, r.m_XMax-r.m_XMin, r.m_Y1-r.m_Y0, sProxy->m_StructExtData, sProxy->m_StructClientData, this, r.m_Var);
5964 currentCustomActiveStructProxy = sProxy;
5965 s = 2; // force s-loop exit
5968 else if( sProxy!=NULL )
5970 sProxy->m_CustomCaptureFocus = false; // force free focus, just in case.
5971 ANT_SET_CURSOR(Arrow);
5977 // If needed, send a 'MouseLeave' message to previously active custom struct
5978 if( g_TwMgr!=NULL && m_CustomActiveStructProxy!=NULL && m_CustomActiveStructProxy!=currentCustomActiveStructProxy )
5981 for( list<CTwMgr::CStructProxy>::iterator it=g_TwMgr->m_StructProxies.begin(); it!=g_TwMgr->m_StructProxies.end() && !found; ++it )
5982 found = (&(*it)==m_CustomActiveStructProxy);
5983 if( found && m_CustomActiveStructProxy->m_CustomMouseLeaveCallback!=NULL )
5984 m_CustomActiveStructProxy->m_CustomMouseLeaveCallback(m_CustomActiveStructProxy->m_StructExtData, m_CustomActiveStructProxy->m_StructClientData, this);
5986 m_CustomActiveStructProxy = currentCustomActiveStructProxy;
5991 // ---------------------------------------------------------------------------
5994 # pragma optimize("", off)
5995 // disable optimizations because the conversion of Enum from unsigned int to double is not always exact if optimized and GraphAPI=DirectX !
5997 static void ANT_CALL PopupCallback(void *_ClientData)
5999 CTwFPU fpu; // force fpu precision
6001 if( g_TwMgr!=NULL && g_TwMgr->m_PopupBar!=NULL )
6003 unsigned int Enum = *(unsigned int *)&_ClientData;
6004 CTwVarAtom *Var = g_TwMgr->m_PopupBar->m_VarEnumLinkedToPopupList;
6005 CTwBar *Bar = g_TwMgr->m_PopupBar->m_BarLinkedToPopupList;
6006 if( Bar!=NULL && Var!=NULL && !Var->m_ReadOnly && IsEnumType(Var->m_Type) )
6008 Var->ValueFromDouble(Enum);
6009 //Bar->UnHighlightLine();
6010 Bar->HaveFocus(true);
6013 TwDeleteBar(g_TwMgr->m_PopupBar);
6014 g_TwMgr->m_PopupBar = NULL;
6018 # pragma optimize("", on)
6021 // ---------------------------------------------------------------------------
6023 bool CTwBar::MouseButton(ETwMouseButtonID _Button, bool _Pressed, int _X, int _Y)
6025 assert(g_TwMgr->m_Graph && g_TwMgr->m_WndHeight>0 && g_TwMgr->m_WndWidth>0);
6026 bool Handled = false;
6029 bool EditInPlaceActive = false;
6030 bool CustomArea = false;
6032 if( !m_IsMinimized )
6034 Handled = (_X>=m_PosX && _X<m_PosX+m_Width && _Y>=m_PosY && _Y<m_PosY+m_Height);
6035 if( _Button==TW_MOUSE_LEFT && m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size() && m_HierTags[m_HighlightedLine].m_Var )
6037 if( m_HierTags[m_HighlightedLine].m_Var->IsGroup() )
6039 if( _Pressed && !g_TwMgr->m_IsRepeatingMousePressed )
6041 CTwVarGroup *Grp = static_cast<CTwVarGroup *>(m_HierTags[m_HighlightedLine].m_Var);
6042 Grp->m_Open = !Grp->m_Open;
6044 ANT_SET_CURSOR(Arrow);
6047 else if( _Pressed && m_HighlightIncrBtn )
6049 static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->Increment(1);
6050 if( g_TwMgr==NULL ) // Mgr might have been destroyed by the client inside a callback call
6054 else if( _Pressed && m_HighlightDecrBtn )
6056 static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->Increment(-1);
6057 if( g_TwMgr==NULL ) // Mgr might have been destroyed by the client inside a callback call
6061 else if( _Pressed && !m_MouseDrag )
6064 m_MouseDragVar = true;
6065 m_MouseOriginX = _X;
6066 m_MouseOriginY = _Y;
6067 m_VarHasBeenIncr = false;
6068 CTwVarAtom * Var = static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var);
6069 if( !Var->m_NoSlider && !Var->m_ReadOnly && m_HighlightRotoBtn )
6072 if( _X>m_PosX+m_VarX1 )
6073 RotoOnLButtonDown(m_PosX+m_VarX2-(1*IncrBtnWidth(m_Font->m_CharHeight))/2, _Y);
6075 RotoOnLButtonDown(_X, _Y);
6077 m_MouseDragVar = true;
6079 else if( (Var->m_Type==TW_TYPE_BOOL8 || Var->m_Type==TW_TYPE_BOOL16 || Var->m_Type==TW_TYPE_BOOL32 || Var->m_Type==TW_TYPE_BOOLCPP) && !Var->m_ReadOnly )
6082 //m_HighlightClickBtn = true;
6083 m_VarHasBeenIncr = true;
6084 m_MouseDragVar = false;
6085 m_MouseDrag = false;
6088 else if( Var->m_Type==TW_TYPE_BUTTON && !Var->m_ReadOnly )
6090 m_HighlightClickBtn = true;
6091 m_MouseDragVar = false;
6092 m_MouseDrag = false;
6094 //else if( (Var->m_Type==TW_TYPE_ENUM8 || Var->m_Type==TW_TYPE_ENUM16 || Var->m_Type==TW_TYPE_ENUM32) && !Var->m_ReadOnly )
6095 else if( IsEnumType(Var->m_Type) && !Var->m_ReadOnly && !g_TwMgr->m_IsRepeatingMousePressed )
6097 m_MouseDragVar = false;
6098 m_MouseDrag = false;
6099 if( g_TwMgr->m_PopupBar!=NULL )
6101 TwDeleteBar(g_TwMgr->m_PopupBar);
6102 g_TwMgr->m_PopupBar = NULL;
6105 CTwMgr::CEnum& e = g_TwMgr->m_Enums[Var->m_Type-TW_TYPE_ENUM_BASE];
6106 g_TwMgr->m_PopupBar = TwNewBar("~ Enum Popup ~");
6107 g_TwMgr->m_PopupBar->m_IsPopupList = true;
6108 g_TwMgr->m_PopupBar->m_Color = m_Color;
6109 g_TwMgr->m_PopupBar->m_DarkText = m_DarkText;
6110 g_TwMgr->m_PopupBar->m_PosX = m_PosX + m_VarX1 - 2;
6111 g_TwMgr->m_PopupBar->m_PosY = m_PosY + m_VarY0 + (m_HighlightedLine+1)*(m_Font->m_CharHeight+m_LineSep);
6112 g_TwMgr->m_PopupBar->m_Width = m_Width - 2*m_Font->m_CharHeight;
6113 g_TwMgr->m_PopupBar->m_LineSep = g_TwMgr->m_PopupBar->m_Sep;
6114 int popHeight0 = (int)e.m_Entries.size()*(m_Font->m_CharHeight+m_Sep) + m_Font->m_CharHeight/2+2;
6115 int popHeight = popHeight0;
6116 if( g_TwMgr->m_PopupBar->m_PosY+popHeight+2 > g_TwMgr->m_WndHeight )
6117 popHeight = g_TwMgr->m_WndHeight-g_TwMgr->m_PopupBar->m_PosY-2;
6118 if( popHeight<popHeight0/2 && popHeight<g_TwMgr->m_WndHeight/2 )
6119 popHeight = min(popHeight0, g_TwMgr->m_WndHeight/2);
6120 if( popHeight<3*(m_Font->m_CharHeight+m_Sep) )
6121 popHeight = 3*(m_Font->m_CharHeight+m_Sep);
6122 g_TwMgr->m_PopupBar->m_Height = popHeight;
6123 g_TwMgr->m_PopupBar->m_VarEnumLinkedToPopupList = Var;
6124 g_TwMgr->m_PopupBar->m_BarLinkedToPopupList = this;
6125 unsigned int CurrentEnumValue = (unsigned int)((int)Var->ValueToDouble());
6126 for( CTwMgr::CEnum::CEntries::iterator It=e.m_Entries.begin(); It!=e.m_Entries.end(); ++It )
6129 sprintf(ID, "%u", It->first);
6130 //ultoa(It->first, ID, 10);
6131 TwAddButton(g_TwMgr->m_PopupBar, ID, PopupCallback, *(void**)&(It->first), NULL);
6132 CTwVar *Btn = g_TwMgr->m_PopupBar->Find(ID);
6135 Btn->m_Label = It->second.c_str();
6136 if( It->first==CurrentEnumValue )
6138 Btn->m_ColorPtr = &m_ColValTextNE;
6139 Btn->m_BgColorPtr = &m_ColGrpBg;
6143 g_TwMgr->m_HelpBarNotUpToDate = false;
6145 else if( (Var->m_ReadOnly && (Var->m_Type==TW_TYPE_CDSTRING || Var->m_Type==TW_TYPE_CDSTDSTRING || Var->m_Type==TW_TYPE_STDSTRING || IsCSStringType(Var->m_Type)) && EditInPlaceAcceptVar(Var))
6146 || (!Var->m_ReadOnly && EditInPlaceAcceptVar(Var)) )
6149 //if( m_DrawIncrDecrBtn )
6150 // dw = 2*IncrBtnWidth(m_Font->m_CharHeight);
6151 if( !m_EditInPlace.m_Active || m_EditInPlace.m_Var!=Var )
6153 EditInPlaceStart(Var, m_VarX1, m_VarY0+(m_HighlightedLine)*(m_Font->m_CharHeight+m_LineSep), m_VarX2-m_VarX1-dw-1);
6154 if( EditInPlaceIsReadOnly() )
6155 EditInPlaceMouseMove(_X, _Y, false);
6156 m_MouseDrag = false;
6157 m_MouseDragVar = false;
6161 EditInPlaceMouseMove(_X, _Y, false);
6163 m_MouseDragVar = false;
6165 EditInPlaceActive = m_EditInPlace.m_Active;
6166 if( Var->m_ReadOnly )
6169 ANT_SET_CURSOR(IBeam);
6171 else if( Var->m_ReadOnly )
6175 ANT_SET_CURSOR(Arrow);
6179 else if ( !_Pressed && m_MouseDragVar )
6181 m_MouseDrag = false;
6182 m_MouseDragVar = false;
6184 m_DrawHandles = false;
6187 RotoOnLButtonUp(_X, _Y);
6189 /* Incr/decr on right or left click
6190 if( !m_VarHasBeenIncr && !static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly )
6192 if( _Button==TW_MOUSE_LEFT )
6193 static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->Increment(-1);
6194 else if( _Button==TW_MOUSE_RIGHT )
6195 static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->Increment(1);
6200 if( static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var)->m_ReadOnly )
6204 ANT_SET_CURSOR(Arrow);
6208 else if( !_Pressed && m_HighlightClickBtn ) // a button variable is activated
6210 m_HighlightClickBtn = false;
6211 m_MouseDragVar = false;
6212 m_MouseDrag = false;
6215 if( !m_HierTags[m_HighlightedLine].m_Var->IsGroup() )
6217 CTwVarAtom * Var = static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var);
6218 if( !Var->m_ReadOnly && Var->m_Type==TW_TYPE_BUTTON && Var->m_Val.m_Button.m_Callback!=NULL )
6220 Var->m_Val.m_Button.m_Callback(Var->m_ClientData);
6221 if( g_TwMgr==NULL ) // Mgr might have been destroyed by the client inside a callback call
6226 else if( !_Pressed )
6228 m_MouseDragVar = false;
6229 m_MouseDrag = false;
6233 else if( _Pressed && !m_MouseDrag && m_Movable && !m_IsPopupList
6234 && ( (_Button==TW_MOUSE_LEFT && _X>=m_PosX+2*m_Font->m_CharHeight && _X<m_PosX+m_Width-2*m_Font->m_CharHeight && _Y>=m_PosY && _Y<m_PosY+m_Font->m_CharHeight)
6235 || (_Button==TW_MOUSE_MIDDLE && _X>=m_PosX && _X<m_PosX+m_Width && _Y>=m_PosY && _Y<m_PosY+m_Height) ) )
6238 m_MouseDragTitle = true;
6239 m_MouseOriginX = _X;
6240 m_MouseOriginY = _Y;
6241 m_HighlightTitle = true;
6242 ANT_SET_CURSOR(Move);
6244 else if( !_Pressed && m_MouseDragTitle )
6246 m_MouseDrag = false;
6247 m_MouseDragTitle = false;
6248 ANT_SET_CURSOR(Arrow);
6250 else if( _Pressed && !m_MouseDrag && !m_IsPopupList && _Button==TW_MOUSE_LEFT && _X>=m_PosX+m_VarX1-3 && _X<m_PosX+m_VarX1+3 && _Y>m_PosY+m_Font->m_CharHeight && _Y<m_PosY+m_VarY0 )
6253 m_MouseDragValWidth = true;
6254 m_MouseOriginX = _X;
6255 m_MouseOriginY = _Y;
6258 else if( !_Pressed && m_MouseDragValWidth )
6260 m_MouseDrag = false;
6261 m_MouseDragValWidth = false;
6262 ANT_SET_CURSOR(Arrow);
6264 else if( _Pressed && !m_MouseDrag && m_NbDisplayedLines<m_NbHierLines && _Button==TW_MOUSE_LEFT && _X>=m_PosX+m_VarX2+2 && _X<m_PosX+m_Width-2 && _Y>=m_ScrollY0 && _Y<m_ScrollY1 )
6267 m_MouseDragScroll = true;
6268 m_MouseOriginX = _X;
6269 m_MouseOriginY = _Y;
6270 m_FirstLine0 = m_FirstLine;
6274 ANT_SET_CURSOR(Arrow);
6277 else if( !_Pressed && m_MouseDragScroll )
6279 m_MouseDrag = false;
6280 m_MouseDragScroll = false;
6281 ANT_SET_CURSOR(Arrow);
6283 else if( _Pressed && _Button==TW_MOUSE_LEFT && _X>=m_PosX+m_VarX2+2 && _X<m_PosX+m_Width-2 && _Y>=m_PosY+m_VarY0 && _Y<m_ScrollY0 )
6291 else if( _Pressed && _Button==TW_MOUSE_LEFT && _X>=m_PosX+m_VarX2+2 && _X<m_PosX+m_Width-2 && _Y>=m_ScrollY1 && _Y<m_PosY+m_VarY1 )
6293 if( m_FirstLine<m_NbHierLines-m_NbDisplayedLines )
6299 else if( _Pressed && !m_MouseDrag && m_Resizable && !m_IsPopupList && _Button==TW_MOUSE_LEFT && _X>=m_PosX && _X<m_PosX+m_Font->m_CharHeight && _Y>=m_PosY && _Y<m_PosY+m_Font->m_CharHeight )
6302 m_MouseDragResizeUL = true;
6303 m_MouseOriginX = _X;
6304 m_MouseOriginY = _Y;
6305 m_ValuesWidthRatio = (m_Width>0) ? (double)m_ValuesWidth/m_Width : 0;
6306 ANT_SET_CURSOR(TopLeft);
6308 else if( !_Pressed && m_MouseDragResizeUL )
6310 m_MouseDrag = false;
6311 m_MouseDragResizeUL = false;
6312 ANT_SET_CURSOR(Arrow);
6314 else if( _Pressed && !m_MouseDrag && m_Resizable && !m_IsPopupList && _Button==TW_MOUSE_LEFT && _X>=m_PosX+m_Width-m_Font->m_CharHeight && _X<m_PosX+m_Width && _Y>=m_PosY && _Y<m_PosY+m_Font->m_CharHeight )
6317 m_MouseDragResizeUR = true;
6318 m_MouseOriginX = _X;
6319 m_MouseOriginY = _Y;
6320 m_ValuesWidthRatio = (m_Width>0) ? (double)m_ValuesWidth/m_Width : 0;
6321 ANT_SET_CURSOR(TopRight);
6323 else if( !_Pressed && m_MouseDragResizeUR )
6325 m_MouseDrag = false;
6326 m_MouseDragResizeUR = false;
6327 ANT_SET_CURSOR(Arrow);
6329 else if( _Pressed && !m_MouseDrag && m_Resizable && !m_IsPopupList && _Button==TW_MOUSE_LEFT && _X>=m_PosX && _X<m_PosX+m_Font->m_CharHeight && _Y>=m_PosY+m_Height-m_Font->m_CharHeight && _Y<m_PosY+m_Height )
6332 m_MouseDragResizeLL = true;
6333 m_MouseOriginX = _X;
6334 m_MouseOriginY = _Y;
6335 m_ValuesWidthRatio = (m_Width>0) ? (double)m_ValuesWidth/m_Width : 0;
6336 ANT_SET_CURSOR(BottomLeft);
6338 else if( !_Pressed && m_MouseDragResizeLL )
6340 m_MouseDrag = false;
6341 m_MouseDragResizeLL = false;
6342 ANT_SET_CURSOR(Arrow);
6344 else if( _Pressed && !m_MouseDrag && m_Resizable && !m_IsPopupList && _Button==TW_MOUSE_LEFT && _X>=m_PosX+m_Width-m_Font->m_CharHeight && _X<m_PosX+m_Width && _Y>=m_PosY+m_Height-m_Font->m_CharHeight && _Y<m_PosY+m_Height )
6347 m_MouseDragResizeLR = true;
6348 m_MouseOriginX = _X;
6349 m_MouseOriginY = _Y;
6350 m_ValuesWidthRatio = (m_Width>0) ? (double)m_ValuesWidth/m_Width : 0;
6351 ANT_SET_CURSOR(BottomRight);
6353 else if( !_Pressed && m_MouseDragResizeLR )
6355 m_MouseDrag = false;
6356 m_MouseDragResizeLR = false;
6357 ANT_SET_CURSOR(Arrow);
6359 else if( _Pressed && !m_IsPopupList && _Button==TW_MOUSE_LEFT && m_HighlightLabelsHeader )
6361 int w = ComputeLabelsWidth(m_Font);
6362 if( w<m_Font->m_CharHeight )
6363 w = m_Font->m_CharHeight;
6364 m_ValuesWidth = m_VarX2 - m_VarX0 - w;
6365 if( m_ValuesWidth<m_Font->m_CharHeight )
6366 m_ValuesWidth = m_Font->m_CharHeight;
6367 if( m_ValuesWidth>m_VarX2 - m_VarX0 )
6368 m_ValuesWidth = max(m_VarX2 - m_VarX0 - m_Font->m_CharHeight, 0);
6370 ANT_SET_CURSOR(Arrow);
6372 else if( _Pressed && !m_IsPopupList && _Button==TW_MOUSE_LEFT && m_HighlightValuesHeader )
6374 int w = ComputeValuesWidth(m_Font);
6375 if( w<2*m_Font->m_CharHeight )
6376 w = 2*m_Font->m_CharHeight; // enough to draw a button
6378 if( m_ValuesWidth>m_VarX2 - m_VarX0 )
6379 m_ValuesWidth = max(m_VarX2 - m_VarX0 - m_Font->m_CharHeight, 0);
6381 ANT_SET_CURSOR(Arrow);
6383 else if( _Pressed && g_TwMgr->m_FontResizable && !m_IsPopupList && _X>=m_PosX+m_Font->m_CharHeight && _X<m_PosX+2*m_Font->m_CharHeight && _Y>m_PosY && _Y<m_PosY+m_Font->m_CharHeight )
6386 if( _Button==TW_MOUSE_LEFT )
6388 if( m_Font==g_DefaultSmallFont )
6389 g_TwMgr->SetFont(g_DefaultNormalFont, true);
6390 else if( m_Font==g_DefaultNormalFont )
6391 g_TwMgr->SetFont(g_DefaultLargeFont, true);
6392 else if( m_Font==g_DefaultLargeFont )
6393 g_TwMgr->SetFont(g_DefaultSmallFont, true);
6395 g_TwMgr->SetFont(g_DefaultNormalFont, true);
6397 else if( _Button==TW_MOUSE_RIGHT )
6399 if( m_Font==g_DefaultSmallFont )
6400 g_TwMgr->SetFont(g_DefaultLargeFont, true);
6401 else if( m_Font==g_DefaultNormalFont )
6402 g_TwMgr->SetFont(g_DefaultSmallFont, true);
6403 else if( m_Font==g_DefaultLargeFont )
6404 g_TwMgr->SetFont(g_DefaultNormalFont, true);
6406 g_TwMgr->SetFont(g_DefaultNormalFont, true);
6409 ANT_SET_CURSOR(Arrow);
6411 else if( _Pressed && m_Iconifiable && !m_IsPopupList && _Button==TW_MOUSE_LEFT && _X>=m_PosX+m_Width-2*m_Font->m_CharHeight && _X<m_PosX+m_Width-m_Font->m_CharHeight && _Y>m_PosY && _Y<m_PosY+m_Font->m_CharHeight )
6414 g_TwMgr->Minimize(this);
6415 ANT_SET_CURSOR(Arrow);
6417 else if( m_IsHelpBar && _Pressed && !g_TwMgr->m_IsRepeatingMousePressed && _X>=m_PosX+m_VarX0 && _X<m_PosX+m_Width-m_Font->m_CharHeight && _Y>m_PosY+m_Height-m_Font->m_CharHeight && _Y<m_PosY+m_Height )
6420 const char *WebPage = "http://www.antisphere.com/Wiki/tools:anttweakbar";
6421 #if defined ANT_WINDOWS
6422 ShellExecute(NULL, "open", WebPage, NULL, NULL, SW_SHOWNORMAL);
6423 #elif defined ANT_UNIX
6424 // brute force: try all the possible browsers (I don't know how to find the default one; someone?)
6425 char DefaultBrowsers[] = "firefox,chrome,opera,mozilla,konqueror,galeon,dillo,netscape";
6426 char *browser = strtok(DefaultBrowsers, ",");
6430 snprintf(cmd, sizeof(cmd), "%s \"%s\" 1>& null &", browser, WebPage);
6431 if( system(cmd) ) {} // avoiding warn_unused_result
6432 browser = strtok(NULL, ","); // grab the next browser
6434 #elif defined ANT_OSX
6436 snprintf(cmd, sizeof(cmd), "open \"%s\" 1>& null &", WebPage);
6437 if( system(cmd) ) {} // avoiding warn_unused_result
6439 ANT_SET_CURSOR(Hand);
6449 if( _Pressed && m_HighlightMaximize )
6451 m_HighlightMaximize = false;
6452 g_TwMgr->Maximize(this);
6453 ANT_SET_CURSOR(Arrow);
6458 if( g_TwMgr!=NULL ) // Mgr might have been destroyed by the client inside a callback call
6459 if( _Pressed && !EditInPlaceActive && m_EditInPlace.m_Active )
6460 EditInPlaceEnd(true);
6462 // Handled by a custom widget?
6463 if( g_TwMgr!=NULL && (!Handled || CustomArea) && !m_IsMinimized && m_CustomRecords.size()>0 )
6465 bool CustomHandled = false;
6466 for( int s=0; s<2; ++s ) // 2 iterations: first for custom widget having focus, second for others if no focused widget.
6467 for( CustomMap::iterator it=m_CustomRecords.begin(); it!=m_CustomRecords.end(); ++it )
6469 CTwMgr::CStructProxy *sProxy = it->first;
6470 const CCustomRecord& r = it->second;
6471 if( (s==1 || sProxy->m_CustomCaptureFocus) && !CustomHandled && sProxy!=NULL && sProxy->m_CustomMouseButtonCallback!=NULL && r.m_XMin<r.m_XMax && r.m_Y0<r.m_Y1 && r.m_YMin<=r.m_YMax && r.m_YMin>=r.m_Y0 && r.m_YMax<=r.m_Y1 )
6473 if( sProxy->m_CustomCaptureFocus || (_X>=r.m_XMin && _X<r.m_XMax && _Y>=r.m_YMin && _Y<r.m_YMax) )
6475 sProxy->m_CustomCaptureFocus = _Pressed;
6476 CustomHandled = sProxy->m_CustomMouseButtonCallback(_Button, _Pressed, _X-r.m_XMin, _Y-r.m_Y0, r.m_XMax-r.m_XMin, r.m_Y1-r.m_Y0, sProxy->m_StructExtData, sProxy->m_StructClientData, this, r.m_Var);
6477 s = 2; // force s-loop exit
6480 else if( sProxy!=NULL )
6482 sProxy->m_CustomCaptureFocus = false; // force free focus, just in case.
6483 ANT_SET_CURSOR(Arrow);
6494 // ---------------------------------------------------------------------------
6496 bool CTwBar::MouseWheel(int _Pos, int _PrevPos, int _MouseX, int _MouseY)
6498 assert(g_TwMgr->m_Graph && g_TwMgr->m_WndHeight>0 && g_TwMgr->m_WndWidth>0);
6502 bool Handled = false;
6503 if( !m_IsMinimized && _MouseX>=m_PosX && _MouseX<m_PosX+m_Width && _MouseY>=m_PosY && _MouseY<m_PosY+m_Height )
6505 if( _Pos>_PrevPos && m_FirstLine>0 )
6510 else if( _Pos<_PrevPos && m_FirstLine<m_NbHierLines-m_NbDisplayedLines )
6516 if( _Pos!=_PrevPos )
6519 if( m_EditInPlace.m_Active )
6520 EditInPlaceEnd(true);
6527 // ---------------------------------------------------------------------------
6529 CTwVarAtom *CTwVarGroup::FindShortcut(int _Key, int _Modifiers, bool *_DoIncr)
6532 int Mask = 0xffffffff;
6533 if( _Key>' ' && _Key<256 ) // don't test SHIFT if _Key is a common key
6534 Mask &= ~TW_KMOD_SHIFT;
6536 // don't test KMOD_NUM and KMOD_CAPS modifiers coming from SDL
6537 Mask &= ~(0x1000); // 0x1000 is the KMOD_NUM value defined in SDL_keysym.h
6538 Mask &= ~(0x2000); // 0x2000 is the KMOD_CAPS value defined in SDL_keysym.h
6540 // complete partial modifiers comming from SDL
6541 if( _Modifiers & TW_KMOD_SHIFT )
6542 _Modifiers |= TW_KMOD_SHIFT;
6543 if( _Modifiers & TW_KMOD_CTRL )
6544 _Modifiers |= TW_KMOD_CTRL;
6545 if( _Modifiers & TW_KMOD_ALT )
6546 _Modifiers |= TW_KMOD_ALT;
6547 if( _Modifiers & TW_KMOD_META )
6548 _Modifiers |= TW_KMOD_META;
6550 for(size_t i=0; i<m_Vars.size(); ++i)
6551 if( m_Vars[i]!=NULL )
6553 if( m_Vars[i]->IsGroup() )
6555 Atom = static_cast<CTwVarGroup *>(m_Vars[i])->FindShortcut(_Key, _Modifiers, _DoIncr);
6561 Atom = static_cast<CTwVarAtom *>(m_Vars[i]);
6562 if( Atom->m_KeyIncr[0]==_Key && (Atom->m_KeyIncr[1]&Mask)==(_Modifiers&Mask) )
6568 else if( Atom->m_KeyDecr[0]==_Key && (Atom->m_KeyDecr[1]&Mask)==(_Modifiers&Mask) )
6579 bool CTwBar::KeyPressed(int _Key, int _Modifiers)
6581 assert(g_TwMgr->m_Graph && g_TwMgr->m_WndHeight>0 && g_TwMgr->m_WndWidth>0);
6582 bool Handled = false;
6586 if( _Key>0 && _Key<TW_KEY_LAST )
6588 /* cf TranslateKey in TwMgr.cpp
6589 // CTRL special cases
6590 if( (_Modifiers&TW_KMOD_CTRL) && !(_Modifiers&TW_KMOD_ALT || _Modifiers&TW_KMOD_META) && _Key>0 && _Key<32 )
6593 // PAD translation (for SDL keysym)
6594 if( _Key>=256 && _Key<=272 ) // 256=SDLK_KP0 ... 272=SDLK_KP_EQUALS
6596 bool Num = ((_Modifiers&TW_KMOD_SHIFT) && !(_Modifiers&0x1000)) || (!(_Modifiers&TW_KMOD_SHIFT) && (_Modifiers&0x1000)); // 0x1000 is SDL's KMOD_NUM
6597 _Modifiers &= ~TW_KMOD_SHIFT; // remove shift modifier
6598 if( _Key==266 ) // SDLK_KP_PERIOD
6599 _Key = Num ? '.' : TW_KEY_DELETE;
6600 else if( _Key==267 ) // SDLK_KP_DIVIDE
6602 else if( _Key==268 ) // SDLK_KP_MULTIPLY
6604 else if( _Key==269 ) // SDLK_KP_MINUS
6606 else if( _Key==270 ) // SDLK_KP_PLUS
6608 else if( _Key==271 ) // SDLK_KP_ENTER
6609 _Key = TW_KEY_RETURN;
6610 else if( _Key==272 ) // SDLK_KP_EQUALS
6612 else if( Num ) // num SDLK_KP0..9
6614 else if( _Key==256 ) // non-num SDLK_KP01
6615 _Key = TW_KEY_INSERT;
6616 else if( _Key==257 ) // non-num SDLK_KP1
6618 else if( _Key==258 ) // non-num SDLK_KP2
6620 else if( _Key==259 ) // non-num SDLK_KP3
6621 _Key = TW_KEY_PAGE_DOWN;
6622 else if( _Key==260 ) // non-num SDLK_KP4
6624 else if( _Key==262 ) // non-num SDLK_KP6
6625 _Key = TW_KEY_RIGHT;
6626 else if( _Key==263 ) // non-num SDLK_KP7
6628 else if( _Key==264 ) // non-num SDLK_KP8
6630 else if( _Key==265 ) // non-num SDLK_KP9
6631 _Key = TW_KEY_PAGE_UP;
6637 TwGetKeyString(&Str, _Key, _Modifiers);
6638 printf("key: %d 0x%04xd %s\n", _Key, _Modifiers, Str.c_str());
6641 if( m_EditInPlace.m_Active )
6643 Handled = EditInPlaceKeyPressed(_Key, _Modifiers);
6647 bool BarActive = (m_DrawHandles || m_IsPopupList) && !m_IsMinimized;
6649 CTwVarAtom *Atom = m_VarRoot.FindShortcut(_Key, _Modifiers, &DoIncr);
6650 if( Atom!=NULL && Atom->m_Visible )
6652 if( !Atom->m_ReadOnly )
6654 Atom->Increment( DoIncr ? +1 : -1 );
6655 if( g_TwMgr==NULL ) // Mgr might have been destroyed by the client inside a callback call
6657 m_HighlightClickBtnAuto = g_TwMgr->m_Timer.GetTime();
6663 else if( BarActive && m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size() && m_HierTags[m_HighlightedLine].m_Var )
6665 if( _Key==TW_KEY_RIGHT )
6667 if( !m_HierTags[m_HighlightedLine].m_Var->IsGroup() )
6669 CTwVarAtom *Atom = static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var);
6670 bool Accept = !Atom->m_NoSlider || Atom->m_Type==TW_TYPE_BUTTON
6671 || Atom->m_Type==TW_TYPE_BOOL8 || Atom->m_Type==TW_TYPE_BOOL16 || Atom->m_Type==TW_TYPE_BOOL32 || Atom->m_Type==TW_TYPE_BOOLCPP
6672 || IsEnumType(Atom->m_Type);
6673 if( !Atom->IsReadOnly() && !m_IsPopupList && Accept )
6675 Atom->Increment(+1);
6676 if( g_TwMgr==NULL ) // Mgr might have been destroyed by the client inside a callback call
6678 m_HighlightClickBtnAuto = g_TwMgr->m_Timer.GetTime();
6684 CTwVarGroup *Grp = static_cast<CTwVarGroup *>(m_HierTags[m_HighlightedLine].m_Var);
6693 else if( _Key==TW_KEY_LEFT )
6695 if( !m_HierTags[m_HighlightedLine].m_Var->IsGroup() )
6697 CTwVarAtom *Atom = static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var);
6698 bool Accept = !Atom->m_NoSlider || Atom->m_Type==TW_TYPE_BUTTON
6699 || Atom->m_Type==TW_TYPE_BOOL8 || Atom->m_Type==TW_TYPE_BOOL16 || Atom->m_Type==TW_TYPE_BOOL32 || Atom->m_Type==TW_TYPE_BOOLCPP
6700 || IsEnumType(Atom->m_Type);
6701 if( !Atom->IsReadOnly() && Accept && !m_IsPopupList )
6703 Atom->Increment(-1);
6704 if( g_TwMgr==NULL ) // Mgr might have been destroyed by the client inside a callback call
6706 m_HighlightClickBtnAuto = g_TwMgr->m_Timer.GetTime();
6712 CTwVarGroup *Grp = static_cast<CTwVarGroup *>(m_HierTags[m_HighlightedLine].m_Var);
6715 Grp->m_Open = false;
6721 else if( _Key==TW_KEY_RETURN )
6723 if( !m_HierTags[m_HighlightedLine].m_Var->IsGroup() )
6725 CTwVarAtom *Atom = static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var);
6726 if( !Atom->IsReadOnly() )
6728 if( Atom->m_Type==TW_TYPE_BUTTON || Atom->m_Type==TW_TYPE_BOOLCPP
6729 || Atom->m_Type==TW_TYPE_BOOL8 || Atom->m_Type==TW_TYPE_BOOL16 || Atom->m_Type==TW_TYPE_BOOL32 )
6731 bool isPopup = m_IsPopupList;
6732 Atom->Increment(+1);
6733 if( g_TwMgr==NULL // Mgr might have been destroyed by the client inside a callback call
6734 || isPopup ) // A popup destroys itself
6736 m_HighlightClickBtnAuto = g_TwMgr->m_Timer.GetTime();
6739 else // if( IsEnumType(Atom->m_Type) )
6741 // simulate a mouse click
6742 int y = m_PosY + m_VarY0 + m_HighlightedLine*(m_Font->m_CharHeight+m_LineSep) + m_Font->m_CharHeight/2;
6743 int x = m_PosX + m_VarX1 + 2;
6744 if( x>m_PosX+m_VarX2-2 )
6745 x = m_PosX + m_VarX2 - 2;
6747 MouseButton(TW_MOUSE_LEFT, true, x, y);
6753 CTwVarGroup *Grp = static_cast<CTwVarGroup *>(m_HierTags[m_HighlightedLine].m_Var);
6754 Grp->m_Open = !Grp->m_Open;
6759 else if( _Key==TW_KEY_UP )
6761 --m_HighlightedLine;
6762 if( m_HighlightedLine<0 )
6764 m_HighlightedLine = 0;
6771 m_HighlightedLineLastValid = m_HighlightedLine;
6774 else if( _Key==TW_KEY_DOWN )
6776 ++m_HighlightedLine;
6777 if( m_HighlightedLine>=(int)m_HierTags.size() )
6779 m_HighlightedLine = (int)m_HierTags.size() - 1;
6780 if( m_FirstLine<m_NbHierLines-m_NbDisplayedLines )
6786 m_HighlightedLineLastValid = m_HighlightedLine;
6789 else if( _Key==TW_KEY_ESCAPE && m_IsPopupList )
6792 CTwBar *LinkedBar = m_BarLinkedToPopupList;
6794 g_TwMgr->m_PopupBar = NULL;
6795 if( LinkedBar!=NULL )
6796 LinkedBar->m_DrawHandles = true;
6797 return true; // this bar has been destroyed
6800 else if( BarActive )
6802 if( _Key==TW_KEY_UP || _Key==TW_KEY_DOWN || _Key==TW_KEY_LEFT || _Key==TW_KEY_RIGHT || _Key==TW_KEY_RETURN )
6804 if( m_HighlightedLineLastValid>=0 && m_HighlightedLineLastValid<(int)m_HierTags.size() )
6805 m_HighlightedLine = m_HighlightedLineLastValid;
6806 else if( m_HierTags.size()>0 )
6808 if( _Key==TW_KEY_UP )
6809 m_HighlightedLine = (int)m_HierTags.size()-1;
6811 m_HighlightedLine = 0;
6815 else if( _Key==TW_KEY_ESCAPE && m_IsPopupList )
6818 CTwBar *LinkedBar = m_BarLinkedToPopupList;
6820 g_TwMgr->m_PopupBar = NULL;
6821 if( LinkedBar!=NULL )
6822 LinkedBar->m_DrawHandles = true;
6823 return true; // this bar has been destroyed
6831 // ---------------------------------------------------------------------------
6833 bool CTwBar::KeyTest(int _Key, int _Modifiers)
6835 assert(g_TwMgr->m_Graph && g_TwMgr->m_WndHeight>0 && g_TwMgr->m_WndWidth>0);
6836 bool Handled = false;
6840 if( _Key>0 && _Key<TW_KEY_LAST )
6842 if( m_EditInPlace.m_Active )
6846 bool BarActive = (m_DrawHandles || m_IsPopupList) && !m_IsMinimized;
6848 CTwVarAtom *Atom = m_VarRoot.FindShortcut(_Key, _Modifiers, &DoIncr);
6849 if( Atom!=NULL && Atom->m_Visible )
6851 else if( BarActive && ( _Key==TW_KEY_RIGHT || _Key==TW_KEY_LEFT || _Key==TW_KEY_UP || _Key==TW_KEY_DOWN
6852 || _Key==TW_KEY_RETURN || (_Key==TW_KEY_ESCAPE && m_IsPopupList) ) )
6859 // ---------------------------------------------------------------------------
6861 bool CTwBar::Show(CTwVar *_Var)
6863 if( _Var==NULL || !_Var->m_Visible )
6868 if( OpenHier(&m_VarRoot, _Var) )
6872 int l = LineInHier(&m_VarRoot, _Var);
6875 int NbLines = (m_VarY1-m_VarY0+1)/(m_Font->m_CharHeight+m_LineSep);
6878 if( l<m_FirstLine || l>=m_FirstLine+NbLines )
6880 m_FirstLine = l-NbLines/2;
6885 if( m_NbDisplayedLines<NbLines )
6887 m_FirstLine -= NbLines-m_NbDisplayedLines;
6893 m_HighlightedLine = l-m_FirstLine;
6901 // ---------------------------------------------------------------------------
6903 bool CTwBar::OpenHier(CTwVarGroup *_Root, CTwVar *_Var)
6905 assert( _Root!=NULL );
6906 for(size_t i=0; i<_Root->m_Vars.size(); ++i)
6907 if( _Root->m_Vars[i]!=NULL )
6909 if( _Var==_Root->m_Vars[i]
6910 || (_Root->m_Vars[i]->IsGroup() && OpenHier(static_cast<CTwVarGroup *>(_Root->m_Vars[i]), _Var)) )
6912 _Root->m_Open = true;
6920 // ---------------------------------------------------------------------------
6922 int CTwBar::LineInHier(CTwVarGroup *_Root, CTwVar *_Var)
6924 assert( _Root!=NULL );
6926 for(size_t i=0; i<_Root->m_Vars.size(); ++i)
6927 if( _Root->m_Vars[i]!=NULL && _Root->m_Vars[i]->m_Visible )
6929 if( _Var==_Root->m_Vars[i] )
6931 else if( _Root->m_Vars[i]->IsGroup() && static_cast<CTwVarGroup *>(_Root->m_Vars[i])->m_Open )
6934 int ll = LineInHier(static_cast<CTwVarGroup *>(_Root->m_Vars[i]), _Var);
6945 // ---------------------------------------------------------------------------
6947 void DrawArc(int _X, int _Y, int _Radius, float _StartAngleDeg, float _EndAngleDeg, color32 _Color) // angles in degree
6949 ITwGraph *Gr = g_TwMgr->m_Graph;
6950 if( Gr==NULL || !Gr->IsDrawing() || _Radius==0 || _StartAngleDeg==_EndAngleDeg )
6953 float startAngle = (float)M_PI*_StartAngleDeg/180;
6954 float endAngle = (float)M_PI*_EndAngleDeg/180;
6955 //float stepAngle = 8/(float)_Radius; // segment length = 8 pixels
6956 float stepAngle = 4/(float)_Radius; // segment length = 4 pixels
6957 if( stepAngle>(float)M_PI/4 )
6958 stepAngle = (float)M_PI/4;
6959 bool fullCircle = fabsf(endAngle-startAngle)>=2.0f*(float)M_PI+fabsf(stepAngle);
6963 numSteps = int((2.0f*(float)M_PI)/stepAngle);
6965 endAngle = 2.0f*(float)M_PI;
6968 numSteps = int(fabsf(endAngle-startAngle)/stepAngle);
6969 if( startAngle>endAngle )
6970 stepAngle = -stepAngle;
6972 int x0 = int(_X + _Radius * cosf(startAngle) + 0.5f);
6973 int y0 = int(_Y - _Radius * sinf(startAngle) + 0.5f);
6975 float angle = startAngle+stepAngle;
6977 for( int i=0; i<numSteps; ++i, angle+=stepAngle )
6979 x1 = int(_X + _Radius * cosf(angle) + 0.5f);
6980 y1 = int(_Y - _Radius * sinf(angle) + 0.5f);
6981 Gr->DrawLine(x0, y0, x1, y1, _Color, true);
6988 x1 = int(_X + _Radius * cosf(startAngle) + 0.5f);
6989 y1 = int(_Y - _Radius * sinf(startAngle) + 0.5f);
6993 x1 = int(_X + _Radius * cosf(endAngle) + 0.5f);
6994 y1 = int(_Y - _Radius * sinf(endAngle) + 0.5f);
6996 Gr->DrawLine(x0, y0, x1, y1, _Color, true);
6999 // ---------------------------------------------------------------------------
7001 CTwBar::CRotoSlider::CRotoSlider()
7005 m_ActiveMiddle = false;
7006 m_Subdiv = 256; // will be recalculated in RotoOnLButtonDown
7009 void CTwBar::RotoDraw()
7011 ITwGraph *Gr = g_TwMgr->m_Graph;
7012 if( Gr==NULL || !Gr->IsDrawing() )
7015 if( m_Roto.m_Active )
7017 DrawArc(m_Roto.m_Origin.x, m_Roto.m_Origin.y, 32, 0, 360, m_ColRoto);
7018 DrawArc(m_Roto.m_Origin.x+1, m_Roto.m_Origin.y, 32, 0, 360, m_ColRoto);
7019 DrawArc(m_Roto.m_Origin.x, m_Roto.m_Origin.y+1, 32, 0, 360, m_ColRoto);
7021 if( m_Roto.m_HasPrevious )
7023 double varMax = RotoGetMax();
7024 double varMin = RotoGetMin();
7025 double varStep = RotoGetStep();
7026 if( varMax<DOUBLE_MAX && varMin>-DOUBLE_MAX && fabs(varStep)>DOUBLE_EPS && m_Roto.m_Subdiv>0 )
7028 double dtMax = 360.0*(varMax-m_Roto.m_ValueAngle0)/((double)m_Roto.m_Subdiv*varStep);//+2;
7029 double dtMin = 360.0*(varMin-m_Roto.m_ValueAngle0)/((double)m_Roto.m_Subdiv*varStep);//-2;
7031 if( dtMax>=0 && dtMax<360 && dtMin<=0 && dtMin>-360 && fabs(dtMax-dtMin)<=360 )
7034 double da = 2.0*M_PI/m_Roto.m_Subdiv;
7036 x1 = m_Roto.m_Origin.x + (int)(40*cos(-M_PI*(m_Roto.m_Angle0+dtMax)/180-da));
7037 y1 = m_Roto.m_Origin.y + (int)(40*sin(-M_PI*(m_Roto.m_Angle0+dtMax)/180-da)+0.5);
7038 x2 = m_Roto.m_Origin.x + (int)(40*cos(-M_PI*(m_Roto.m_Angle0+dtMax-10)/180-da));
7039 y2 = m_Roto.m_Origin.y + (int)(40*sin(-M_PI*(m_Roto.m_Angle0+dtMax-10)/180-da)+0.5);
7040 Gr->DrawLine(m_Roto.m_Origin.x, m_Roto.m_Origin.y, x1, y1, m_ColRotoBound, true);
7041 Gr->DrawLine(m_Roto.m_Origin.x+1, m_Roto.m_Origin.y, x1+1, y1, m_ColRotoBound, true);
7042 Gr->DrawLine(m_Roto.m_Origin.x, m_Roto.m_Origin.y+1, x1, y1+1, m_ColRotoBound, true);
7043 Gr->DrawLine(x1, y1, x2, y2, m_ColRotoBound, true);
7044 Gr->DrawLine(x1+1, y1, x2+1, y2, m_ColRotoBound, true);
7045 Gr->DrawLine(x1, y1+1, x2, y2+1, m_ColRotoBound, true);
7047 x1 = m_Roto.m_Origin.x + (int)(40*cos(-M_PI*(m_Roto.m_Angle0+dtMin)/180+da));
7048 y1 = m_Roto.m_Origin.y + (int)(40*sin(-M_PI*(m_Roto.m_Angle0+dtMin)/180+da)+0.5);
7049 x2 = m_Roto.m_Origin.x + (int)(40*cos(-M_PI*(m_Roto.m_Angle0+dtMin+10)/180+da));
7050 y2 = m_Roto.m_Origin.y + (int)(40*sin(-M_PI*(m_Roto.m_Angle0+dtMin+10)/180+da)+0.5);
7051 Gr->DrawLine(m_Roto.m_Origin.x, m_Roto.m_Origin.y, x1, y1, m_ColRotoBound, true);
7052 Gr->DrawLine(m_Roto.m_Origin.x+1, m_Roto.m_Origin.y, x1+1, y1, m_ColRotoBound, true);
7053 Gr->DrawLine(m_Roto.m_Origin.x, m_Roto.m_Origin.y+1, x1, y1+1, m_ColRotoBound, true);
7054 Gr->DrawLine(x1, y1, x2, y2, m_ColRotoBound, true);
7055 Gr->DrawLine(x1+1, y1, x2+1, y2, m_ColRotoBound, true);
7056 Gr->DrawLine(x1, y1+1, x2, y2+1, m_ColRotoBound, true);
7061 Gr->DrawLine(m_Roto.m_Origin.x+1, m_Roto.m_Origin.y, m_Roto.m_Current.x+1, m_Roto.m_Current.y, m_ColRotoVal, true);
7062 Gr->DrawLine(m_Roto.m_Origin.x, m_Roto.m_Origin.y+1, m_Roto.m_Current.x, m_Roto.m_Current.y+1, m_ColRotoVal, true);
7063 Gr->DrawLine(m_Roto.m_Origin.x, m_Roto.m_Origin.y, m_Roto.m_Current.x, m_Roto.m_Current.y, m_ColRotoVal, true);
7065 if( fabs(m_Roto.m_AngleDT)>=1 )
7067 DrawArc(m_Roto.m_Origin.x, m_Roto.m_Origin.y, 32, float(m_Roto.m_Angle0), float(m_Roto.m_Angle0+m_Roto.m_AngleDT-1), m_ColRotoVal);
7068 DrawArc(m_Roto.m_Origin.x+1, m_Roto.m_Origin.y, 32, float(m_Roto.m_Angle0), float(m_Roto.m_Angle0+m_Roto.m_AngleDT-1), m_ColRotoVal);
7069 DrawArc(m_Roto.m_Origin.x, m_Roto.m_Origin.y+1, 32, float(m_Roto.m_Angle0), float(m_Roto.m_Angle0+m_Roto.m_AngleDT-1), m_ColRotoVal);
7074 double CTwBar::RotoGetValue() const
7076 assert(m_Roto.m_Var!=NULL);
7077 return m_Roto.m_Var->ValueToDouble();
7080 void CTwBar::RotoSetValue(double _Val)
7082 assert(m_Roto.m_Var!=NULL);
7083 if( _Val!=m_Roto.m_CurrentValue )
7085 m_Roto.m_CurrentValue = _Val;
7086 m_Roto.m_Var->ValueFromDouble(_Val);
7091 double CTwBar::RotoGetMin() const
7093 assert(m_Roto.m_Var!=NULL);
7094 double min = -DOUBLE_MAX;
7095 m_Roto.m_Var->MinMaxStepToDouble(&min, NULL, NULL);
7099 double CTwBar::RotoGetMax() const
7101 assert(m_Roto.m_Var!=NULL);
7102 double max = DOUBLE_MAX;
7103 m_Roto.m_Var->MinMaxStepToDouble(NULL, &max, NULL);
7107 double CTwBar::RotoGetStep() const
7109 assert(m_Roto.m_Var!=NULL);
7111 m_Roto.m_Var->MinMaxStepToDouble(NULL, NULL, &step);
7115 double CTwBar::RotoGetSteppedValue() const
7117 double d = m_Roto.m_PreciseValue-m_Roto.m_Value0;
7118 double n = int(d/RotoGetStep());
7119 return m_Roto.m_Value0 + RotoGetStep()*n;
7122 void CTwBar::RotoOnMouseMove(int _X, int _Y)
7125 if( m_Roto.m_Active )
7127 m_Roto.m_Current = p;
7128 RotoSetValue(RotoGetSteppedValue());
7133 float r = sqrtf(float( (m_Roto.m_Current.x-m_Roto.m_Origin.x)*(m_Roto.m_Current.x-m_Roto.m_Origin.x)
7134 + (m_Roto.m_Current.y-m_Roto.m_Origin.y)*(m_Roto.m_Current.y-m_Roto.m_Origin.y)));
7135 if( r>m_RotoMinRadius )
7137 t = - atan2(double(m_Roto.m_Current.y-m_Roto.m_Origin.y), double(m_Roto.m_Current.x-m_Roto.m_Origin.x));
7138 ti = (int((t/(2.0*M_PI)+1.0)*NB_ROTO_CURSORS+0.5)) % NB_ROTO_CURSORS;
7139 if( m_Roto.m_HasPrevious )
7141 CPoint v0 = m_Roto.m_Previous-m_Roto.m_Origin;
7142 CPoint v1 = m_Roto.m_Current-m_Roto.m_Origin;
7143 double l0 = sqrt(double(v0.x*v0.x+v0.y*v0.y));
7144 double l1 = sqrt(double(v1.x*v1.x+v1.y*v1.y));
7145 double dt = acos(max(-1+1.0e-30,min(1-1.0e-30,double(v0.x*v1.x+v0.y*v1.y)/(l0*l1))));
7146 if( v0.x*v1.y-v0.y*v1.x>0 )
7148 double preciseInc = double(m_Roto.m_Subdiv) * dt/(2.0*M_PI) * RotoGetStep();
7149 if( preciseInc>RotoGetStep() || preciseInc<-RotoGetStep() )
7151 m_Roto.m_PreciseValue += preciseInc;
7152 if( m_Roto.m_PreciseValue>RotoGetMax() )
7154 m_Roto.m_PreciseValue = RotoGetMax();
7155 m_Roto.m_Value0 = RotoGetMax();
7157 double da = 360*(RotoGetMax()-m_Roto.m_ValueAngle0)/(double(m_Roto.m_Subdiv)*RotoGetStep());
7158 m_Roto.m_Angle0 = ((int((t/(2.0*M_PI)+1.0)*360.0+0.5)) % 360) - da;
7159 m_Roto.m_AngleDT = da;
7161 else if( m_Roto.m_PreciseValue<RotoGetMin() )
7163 m_Roto.m_PreciseValue = RotoGetMin();
7164 m_Roto.m_Value0 = RotoGetMin();
7166 double da = 360*(RotoGetMin()-m_Roto.m_ValueAngle0)/(double(m_Roto.m_Subdiv)*RotoGetStep());
7167 m_Roto.m_Angle0 = ((int((t/(2.0*M_PI)+1.0)*360.0+0.5)) % 360) - da;
7168 m_Roto.m_AngleDT = da;
7170 m_Roto.m_Previous = m_Roto.m_Current;
7171 m_Roto.m_AngleDT += 180.0*dt/M_PI;
7176 m_Roto.m_Previous = m_Roto.m_Current;
7177 m_Roto.m_Value0 = RotoGetValue();
7178 m_Roto.m_PreciseValue = m_Roto.m_Value0;
7179 m_Roto.m_HasPrevious = true;
7180 m_Roto.m_Angle0 = (int((t/(2.0*M_PI)+1.0)*360.0+0.5)) % 360;
7181 m_Roto.m_ValueAngle0 = m_Roto.m_Value0;
7182 m_Roto.m_AngleDT = 0;
7187 if( m_Roto.m_HasPrevious )
7189 RotoSetValue(RotoGetSteppedValue());
7190 m_Roto.m_Value0 = RotoGetValue();
7191 m_Roto.m_ValueAngle0 = m_Roto.m_Value0;
7192 m_Roto.m_PreciseValue = m_Roto.m_Value0;
7193 m_Roto.m_Angle0 = 0;
7195 m_Roto.m_HasPrevious = false;
7196 m_Roto.m_AngleDT = 0;
7198 if( ti>=0 && ti<NB_ROTO_CURSORS )
7199 ANT_SET_ROTO_CURSOR(ti);
7201 ANT_SET_CURSOR(Center);
7205 if( m_HighlightRotoBtn )
7206 ANT_SET_CURSOR(Point);
7208 ANT_SET_CURSOR(Arrow);
7212 void CTwBar::RotoOnLButtonDown(int _X, int _Y)
7215 if( !m_Roto.m_Active && m_HighlightedLine>=0 && m_HighlightedLine<(int)m_HierTags.size() && m_HierTags[m_HighlightedLine].m_Var && !m_HierTags[m_HighlightedLine].m_Var->IsGroup() )
7217 m_Roto.m_Var = static_cast<CTwVarAtom *>(m_HierTags[m_HighlightedLine].m_Var);
7218 int y = m_PosY + m_VarY0 + m_HighlightedLine*(m_Font->m_CharHeight+m_LineSep) + m_Font->m_CharHeight/2;
7219 m_Roto.m_Origin = CPoint(p.x, y); //r.CenterPoint().y);
7220 m_Roto.m_Current = p;
7221 m_Roto.m_Active = true;
7222 m_Roto.m_HasPrevious = false;
7223 m_Roto.m_Angle0 = 0;
7224 m_Roto.m_AngleDT = 0;
7227 m_Roto.m_Value0 = RotoGetValue();
7228 m_Roto.m_CurrentValue = m_Roto.m_Value0;
7229 m_Roto.m_ValueAngle0 = m_Roto.m_Value0;
7230 m_Roto.m_PreciseValue = m_Roto.m_Value0;
7231 //RotoSetValue(RotoGetSteppedValue()); Not here
7234 m_Roto.m_Subdiv = m_RotoNbSubdiv;
7235 // re-adjust m_Subdiv if needed:
7236 double min=-DOUBLE_MAX, max=DOUBLE_MAX, step=1;
7237 m_Roto.m_Var->MinMaxStepToDouble(&min, &max, &step);
7238 if( fabs(step)>0 && min>-DOUBLE_MAX && max<DOUBLE_MAX )
7240 double dsubdiv = fabs(max-min)/fabs(step)+0.5;
7241 if( dsubdiv<m_RotoNbSubdiv/3 )
7242 m_Roto.m_Subdiv = 3*(int)dsubdiv;
7245 ANT_SET_CURSOR(Center);
7249 void CTwBar::RotoOnLButtonUp(int /*_X*/, int /*_Y*/)
7251 if( !m_Roto.m_ActiveMiddle )
7253 //if( m_Roto.m_Var )
7254 // RotoSetValue(RotoGetSteppedValue());
7256 m_Roto.m_Var = NULL;
7257 m_Roto.m_Active = false;
7261 void CTwBar::RotoOnMButtonDown(int _X, int _Y)
7263 if( !m_Roto.m_Active )
7265 m_Roto.m_ActiveMiddle = true;
7266 RotoOnLButtonDown(_X, _Y);
7270 void CTwBar::RotoOnMButtonUp(int _X, int _Y)
7272 if( m_Roto.m_ActiveMiddle )
7274 m_Roto.m_ActiveMiddle = false;
7275 RotoOnLButtonUp(_X, _Y);
7280 // ---------------------------------------------------------------------------
7282 CTwBar::CEditInPlace::CEditInPlace()
7284 assert( g_TwMgr!=NULL && g_TwMgr->m_Graph!=NULL );
7288 m_EditTextObj = g_TwMgr->m_Graph->NewTextObj();
7289 m_EditSelTextObj = g_TwMgr->m_Graph->NewTextObj();
7291 m_X = m_Y = m_Width = 0;
7294 CTwBar::CEditInPlace::~CEditInPlace()
7296 assert( g_TwMgr!=NULL && g_TwMgr->m_Graph!=NULL );
7299 g_TwMgr->m_Graph->DeleteTextObj(m_EditTextObj);
7300 if( m_EditSelTextObj )
7301 g_TwMgr->m_Graph->DeleteTextObj(m_EditSelTextObj);
7304 bool CTwBar::EditInPlaceIsReadOnly()
7306 if( m_EditInPlace.m_Var==NULL )
7308 else if( m_EditInPlace.m_Var->m_ReadOnly )
7310 else if( m_EditInPlace.m_Var->m_Type==TW_TYPE_CDSTRING && ((m_EditInPlace.m_Var->m_Ptr==NULL && m_EditInPlace.m_Var->m_SetCallback==NULL) || (m_EditInPlace.m_Var->m_Ptr!=NULL && g_TwMgr->m_CopyCDStringToClient==NULL)) )
7312 else if( m_EditInPlace.m_Var->m_Type==TW_TYPE_CDSTDSTRING && m_EditInPlace.m_Var->m_SetCallback==NULL )
7314 else if( m_EditInPlace.m_Var->m_Type==TW_TYPE_STDSTRING && ((m_EditInPlace.m_Var->m_Ptr==NULL && m_EditInPlace.m_Var->m_SetCallback==NULL) || (m_EditInPlace.m_Var->m_Ptr!=NULL && g_TwMgr->m_CopyStdStringToClient==NULL)) )
7320 void CTwBar::EditInPlaceDraw()
7322 if( !m_EditInPlace.m_Active || m_EditInPlace.m_Var==NULL || m_EditInPlace.m_Width<=0 )
7325 // adjust m_FirstChar to see the caret, and extract the visible sub-string
7326 int i, StringLen = (int)m_EditInPlace.m_String.length();
7327 if( m_EditInPlace.m_FirstChar>m_EditInPlace.m_CaretPos )
7328 m_EditInPlace.m_FirstChar = m_EditInPlace.m_CaretPos;
7329 int SubstrWidth = 0;
7330 for( i=min(m_EditInPlace.m_CaretPos, StringLen-1); i>=0 && SubstrWidth<m_EditInPlace.m_Width; --i )
7332 unsigned char u = m_EditInPlace.m_String.c_str()[i];
7333 SubstrWidth += m_Font->m_CharWidth[u];
7335 int FirstChar = max(0, i);
7336 if( SubstrWidth>=m_EditInPlace.m_Width )
7338 if( m_EditInPlace.m_FirstChar<FirstChar && FirstChar<StringLen )
7339 m_EditInPlace.m_FirstChar = FirstChar;
7340 if( m_EditInPlace.m_CaretPos==m_EditInPlace.m_FirstChar && m_EditInPlace.m_FirstChar>0 )
7341 --m_EditInPlace.m_FirstChar;
7343 for( i=m_EditInPlace.m_FirstChar; i<StringLen && SubstrWidth<m_EditInPlace.m_Width; ++i )
7345 unsigned char u = m_EditInPlace.m_String.c_str()[i];
7346 SubstrWidth += m_Font->m_CharWidth[u];
7349 if( SubstrWidth>=m_EditInPlace.m_Width )
7351 string Substr = m_EditInPlace.m_String.substr( m_EditInPlace.m_FirstChar, LastChar-m_EditInPlace.m_FirstChar );
7353 // compute caret x pos
7354 int CaretX = m_PosX + m_EditInPlace.m_X;
7355 for( i=m_EditInPlace.m_FirstChar; i<m_EditInPlace.m_CaretPos && i<StringLen; ++i )
7357 unsigned char u = m_EditInPlace.m_String.c_str()[i];
7358 CaretX += m_Font->m_CharWidth[u];
7362 color32 ColText = EditInPlaceIsReadOnly() ? m_ColValTextRO : m_ColEditText;
7363 color32 ColBg = EditInPlaceIsReadOnly() ? m_ColValBg : m_ColEditBg;
7364 g_TwMgr->m_Graph->BuildText(m_EditInPlace.m_EditTextObj, &Substr, NULL, NULL, 1, m_Font, 0, m_EditInPlace.m_Width);
7365 g_TwMgr->m_Graph->DrawText(m_EditInPlace.m_EditTextObj, m_PosX+m_EditInPlace.m_X, m_PosY+m_EditInPlace.m_Y, ColText, ColBg);
7367 // draw selected text
7368 string StrSelected = "";
7369 if( m_EditInPlace.m_CaretPos>m_EditInPlace.m_SelectionStart )
7371 int FirstSel = max(m_EditInPlace.m_SelectionStart, m_EditInPlace.m_FirstChar);
7372 int LastSel = min(m_EditInPlace.m_CaretPos, LastChar);
7373 StrSelected = m_EditInPlace.m_String.substr( FirstSel, LastSel-FirstSel );
7377 int FirstSel = max(m_EditInPlace.m_CaretPos, m_EditInPlace.m_FirstChar);
7378 int LastSel = min(m_EditInPlace.m_SelectionStart, LastChar);
7379 StrSelected = m_EditInPlace.m_String.substr( FirstSel, LastSel-FirstSel );
7382 for( i=0; i<(int)StrSelected.length(); ++i )
7384 unsigned char u = StrSelected.c_str()[i];
7385 SelWidth += m_Font->m_CharWidth[u];
7387 if( SelWidth>0 && StrSelected.length()>0 )
7389 color32 ColSelBg = EditInPlaceIsReadOnly() ? m_ColValTextRO : m_ColEditSelBg;
7390 g_TwMgr->m_Graph->BuildText(m_EditInPlace.m_EditSelTextObj, &StrSelected, NULL, NULL, 1, m_Font, 0, SelWidth);
7391 if ( m_EditInPlace.m_CaretPos>m_EditInPlace.m_SelectionStart )
7392 g_TwMgr->m_Graph->DrawText(m_EditInPlace.m_EditSelTextObj, CaretX-SelWidth, m_PosY+m_EditInPlace.m_Y, m_ColEditSelText, ColSelBg);
7394 g_TwMgr->m_Graph->DrawText(m_EditInPlace.m_EditSelTextObj, CaretX, m_PosY+m_EditInPlace.m_Y, m_ColEditSelText, ColSelBg);
7398 if( CaretX<=m_PosX+m_EditInPlace.m_X+m_EditInPlace.m_Width )
7399 g_TwMgr->m_Graph->DrawLine( CaretX, m_PosY+m_EditInPlace.m_Y+1, CaretX, m_PosY+m_EditInPlace.m_Y+m_Font->m_CharHeight, m_ColEditText );
7402 bool CTwBar::EditInPlaceAcceptVar(const CTwVarAtom* _Var)
7406 if( _Var->m_Type>=TW_TYPE_CHAR && _Var->m_Type<=TW_TYPE_DOUBLE )
7408 if( _Var->m_Type==TW_TYPE_CDSTRING || _Var->m_Type==TW_TYPE_CDSTDSTRING || _Var->m_Type==TW_TYPE_STDSTRING )
7410 if( IsCSStringType(_Var->m_Type) )
7416 void CTwBar::EditInPlaceStart(CTwVarAtom* _Var, int _X, int _Y, int _Width)
7418 if( m_EditInPlace.m_Active )
7419 EditInPlaceEnd(true);
7421 m_EditInPlace.m_Active = true;
7422 m_EditInPlace.m_Var = _Var;
7423 m_EditInPlace.m_X = _X;
7424 m_EditInPlace.m_Y = _Y;
7425 m_EditInPlace.m_Width = _Width;
7426 m_EditInPlace.m_Var->ValueToString(&m_EditInPlace.m_String);
7427 if( m_EditInPlace.m_Var->m_Type==TW_TYPE_CHAR )
7428 m_EditInPlace.m_String = m_EditInPlace.m_String.substr(0, 1);
7429 m_EditInPlace.m_CaretPos = (int)m_EditInPlace.m_String.length();
7430 if( EditInPlaceIsReadOnly() )
7431 m_EditInPlace.m_SelectionStart = m_EditInPlace.m_CaretPos;
7433 m_EditInPlace.m_SelectionStart = 0;
7434 m_EditInPlace.m_FirstChar = 0;
7437 void CTwBar::EditInPlaceEnd(bool _Commit)
7439 if( _Commit && m_EditInPlace.m_Active && m_EditInPlace.m_Var!=NULL )
7441 if( m_EditInPlace.m_Var->m_Type==TW_TYPE_CDSTRING || m_EditInPlace.m_Var->m_Type==TW_TYPE_CDSTDSTRING )
7443 if( m_EditInPlace.m_Var->m_SetCallback!=NULL )
7445 const char *String = m_EditInPlace.m_String.c_str();
7446 m_EditInPlace.m_Var->m_SetCallback(&String, m_EditInPlace.m_Var->m_ClientData);
7448 else if( m_EditInPlace.m_Var->m_Type!=TW_TYPE_CDSTDSTRING )
7450 char **StringPtr = (char **)m_EditInPlace.m_Var->m_Ptr;
7451 if( StringPtr!=NULL && g_TwMgr->m_CopyCDStringToClient!=NULL )
7452 g_TwMgr->m_CopyCDStringToClient(StringPtr, m_EditInPlace.m_String.c_str());
7455 else if( m_EditInPlace.m_Var->m_Type==TW_TYPE_STDSTRING )
7457 // this case should never happened: TW_TYPE_STDSTRING are converted to TW_TYPE_CDSTDSTRING by TwAddVar
7458 if( m_EditInPlace.m_Var->m_SetCallback!=NULL )
7459 m_EditInPlace.m_Var->m_SetCallback(&(m_EditInPlace.m_String), m_EditInPlace.m_Var->m_ClientData);
7462 string *StringPtr = (string *)m_EditInPlace.m_Var->m_Ptr;
7463 if( StringPtr!=NULL && g_TwMgr->m_CopyStdStringToClient!=NULL )
7464 g_TwMgr->m_CopyStdStringToClient(*StringPtr, m_EditInPlace.m_String);
7467 else if( IsCSStringType(m_EditInPlace.m_Var->m_Type) )
7469 int n = TW_CSSTRING_SIZE(m_EditInPlace.m_Var->m_Type);
7472 if( (int)m_EditInPlace.m_String.length()>n-1 )
7473 m_EditInPlace.m_String.resize(n-1);
7474 if( m_EditInPlace.m_Var->m_SetCallback!=NULL )
7475 m_EditInPlace.m_Var->m_SetCallback(m_EditInPlace.m_String.c_str(), m_EditInPlace.m_Var->m_ClientData);
7476 else if( m_EditInPlace.m_Var->m_Ptr!=NULL )
7479 strncpy((char *)m_EditInPlace.m_Var->m_Ptr, m_EditInPlace.m_String.c_str(), n-1);
7480 ((char *)m_EditInPlace.m_Var->m_Ptr)[n-1] = '\0';
7486 double Val = 0, Min = 0, Max = 0, Step = 0;
7488 if( m_EditInPlace.m_Var->m_Type==TW_TYPE_CHAR )
7490 unsigned char Char = 0;
7491 n = sscanf(m_EditInPlace.m_String.c_str(), "%c", &Char);
7495 n = sscanf(m_EditInPlace.m_String.c_str(), "%lf", &Val);
7498 m_EditInPlace.m_Var->MinMaxStepToDouble(&Min, &Max, &Step);
7503 m_EditInPlace.m_Var->ValueFromDouble(Val);
7506 if( g_TwMgr!=NULL ) // Mgr might have been destroyed by the client inside a callback call
7509 m_EditInPlace.m_Active = false;
7510 m_EditInPlace.m_Var = NULL;
7513 bool CTwBar::EditInPlaceKeyPressed(int _Key, int _Modifiers)
7515 if( !m_EditInPlace.m_Active )
7517 bool Handled = true; // if EditInPlace is active, it catches all key events
7518 bool DoCopy = false, DoPaste = false;
7523 EditInPlaceEnd(false);
7526 EditInPlaceEnd(true);
7529 if( _Modifiers==TW_KMOD_SHIFT )
7530 m_EditInPlace.m_CaretPos = max(0, m_EditInPlace.m_CaretPos-1);
7533 if( m_EditInPlace.m_SelectionStart!=m_EditInPlace.m_CaretPos )
7534 m_EditInPlace.m_CaretPos = min(m_EditInPlace.m_SelectionStart, m_EditInPlace.m_CaretPos);
7536 m_EditInPlace.m_CaretPos = max(0, m_EditInPlace.m_CaretPos-1);
7537 m_EditInPlace.m_SelectionStart = m_EditInPlace.m_CaretPos;
7541 if( _Modifiers==TW_KMOD_SHIFT )
7542 m_EditInPlace.m_CaretPos = min((int)m_EditInPlace.m_String.length(), m_EditInPlace.m_CaretPos+1);
7545 if( m_EditInPlace.m_SelectionStart!=m_EditInPlace.m_CaretPos )
7546 m_EditInPlace.m_CaretPos = max(m_EditInPlace.m_SelectionStart, m_EditInPlace.m_CaretPos);
7548 m_EditInPlace.m_CaretPos = min((int)m_EditInPlace.m_String.length(), m_EditInPlace.m_CaretPos+1);
7549 m_EditInPlace.m_SelectionStart = m_EditInPlace.m_CaretPos;
7552 case TW_KEY_BACKSPACE:
7553 if( !EditInPlaceIsReadOnly() )
7555 if( m_EditInPlace.m_SelectionStart==m_EditInPlace.m_CaretPos )
7556 m_EditInPlace.m_SelectionStart = max(0, m_EditInPlace.m_CaretPos-1);
7557 EditInPlaceEraseSelect();
7561 if( !EditInPlaceIsReadOnly() )
7563 if( m_EditInPlace.m_SelectionStart==m_EditInPlace.m_CaretPos )
7564 m_EditInPlace.m_SelectionStart = min(m_EditInPlace.m_CaretPos+1, (int)m_EditInPlace.m_String.length());
7565 EditInPlaceEraseSelect();
7569 m_EditInPlace.m_CaretPos = 0;
7570 if( _Modifiers!=TW_KMOD_SHIFT )
7571 m_EditInPlace.m_SelectionStart = m_EditInPlace.m_CaretPos;
7574 m_EditInPlace.m_CaretPos = (int)m_EditInPlace.m_String.length();
7575 if( _Modifiers!=TW_KMOD_SHIFT )
7576 m_EditInPlace.m_SelectionStart = m_EditInPlace.m_CaretPos;
7579 if( _Modifiers==TW_KMOD_CTRL )
7581 else if( _Modifiers==TW_KMOD_SHIFT )
7585 if( _Modifiers==TW_KMOD_CTRL )
7587 if( _Key=='c' || _Key=='C' )
7589 else if( _Key=='v' || _Key=='V' )
7592 else if( _Key>=32 && _Key<=255 )
7594 if( !EditInPlaceIsReadOnly() && m_EditInPlace.m_CaretPos>=0 && m_EditInPlace.m_CaretPos<=(int)m_EditInPlace.m_String.length() )
7596 if( m_EditInPlace.m_SelectionStart!=m_EditInPlace.m_CaretPos )
7597 EditInPlaceEraseSelect();
7598 string Str(1, (char)_Key);
7599 m_EditInPlace.m_String.insert(m_EditInPlace.m_CaretPos, Str);
7600 ++m_EditInPlace.m_CaretPos;
7601 m_EditInPlace.m_SelectionStart = m_EditInPlace.m_CaretPos;
7606 if( DoPaste && !EditInPlaceIsReadOnly() )
7608 if( m_EditInPlace.m_SelectionStart!=m_EditInPlace.m_CaretPos )
7609 EditInPlaceEraseSelect();
7611 if( EditInPlaceGetClipboard(&Str) && Str.length()>0 )
7613 m_EditInPlace.m_String.insert(m_EditInPlace.m_CaretPos, Str);
7614 m_EditInPlace.m_CaretPos += (int)Str.length();
7615 m_EditInPlace.m_SelectionStart = m_EditInPlace.m_CaretPos;
7621 if( m_EditInPlace.m_CaretPos>m_EditInPlace.m_SelectionStart )
7622 Str = m_EditInPlace.m_String.substr(m_EditInPlace.m_SelectionStart, m_EditInPlace.m_CaretPos-m_EditInPlace.m_SelectionStart);
7623 else if( m_EditInPlace.m_CaretPos<m_EditInPlace.m_SelectionStart )
7624 Str = m_EditInPlace.m_String.substr(m_EditInPlace.m_CaretPos, m_EditInPlace.m_SelectionStart-m_EditInPlace.m_CaretPos);
7625 EditInPlaceSetClipboard(Str);
7632 bool CTwBar::EditInPlaceEraseSelect()
7634 assert(m_EditInPlace.m_Active);
7635 if( !EditInPlaceIsReadOnly() && m_EditInPlace.m_SelectionStart!=m_EditInPlace.m_CaretPos )
7637 int PosMin = min( m_EditInPlace.m_CaretPos, m_EditInPlace.m_SelectionStart );
7638 m_EditInPlace.m_String.erase( PosMin, abs(m_EditInPlace.m_CaretPos - m_EditInPlace.m_SelectionStart) );
7639 m_EditInPlace.m_SelectionStart = m_EditInPlace.m_CaretPos = PosMin;
7640 if( m_EditInPlace.m_FirstChar>PosMin )
7641 m_EditInPlace.m_FirstChar = PosMin;
7649 bool CTwBar::EditInPlaceMouseMove(int _X, int _Y, bool _Select)
7651 if ( !m_EditInPlace.m_Active || _Y<m_PosY+m_EditInPlace.m_Y || _Y>m_PosY+m_EditInPlace.m_Y+m_Font->m_CharHeight )
7654 int i, CaretX = m_PosX+m_EditInPlace.m_X;
7655 for( i=m_EditInPlace.m_FirstChar; i<(int)m_EditInPlace.m_String.length() && CaretX<m_PosX+m_EditInPlace.m_X+m_EditInPlace.m_Width; ++i )
7657 unsigned char u = m_EditInPlace.m_String.c_str()[i];
7658 int CharWidth = m_Font->m_CharWidth[u];
7659 if( _X < CaretX + CharWidth / 2 )
7661 CaretX += CharWidth;
7663 if( CaretX>=m_PosX+m_EditInPlace.m_X+m_EditInPlace.m_Width )
7666 m_EditInPlace.m_CaretPos = i;
7668 m_EditInPlace.m_SelectionStart = m_EditInPlace.m_CaretPos;
7673 bool CTwBar::EditInPlaceGetClipboard(std::string *_OutString)
7675 assert( _OutString!=NULL );
7676 *_OutString = m_EditInPlace.m_Clipboard; // default implementation
7678 #if defined ANT_WINDOWS
7680 if( !IsClipboardFormatAvailable(CF_TEXT) )
7682 if( !OpenClipboard(NULL) )
7684 HGLOBAL TextHandle = GetClipboardData(CF_TEXT);
7685 if( TextHandle!=NULL )
7687 const char *TextString = static_cast<char *>(GlobalLock(TextHandle));
7688 if( TextHandle!=NULL )
7690 *_OutString = TextString;
7691 GlobalUnlock(TextHandle);
7696 #elif defined ANT_UNIX
7698 if( g_TwMgr->m_CurrentXDisplay!=NULL )
7701 char *Buffer = XFetchBytes(g_TwMgr->m_CurrentXDisplay, &NbBytes);
7706 char *Text = new char[NbBytes+1];
7707 memcpy(Text, Buffer, NbBytes);
7708 Text[NbBytes] = '\0';
7722 bool CTwBar::EditInPlaceSetClipboard(const std::string& _String)
7724 if( _String.length()<=0 )
7725 return false; // keep last clipboard
7726 m_EditInPlace.m_Clipboard = _String; // default implementation
7728 #if defined ANT_WINDOWS
7730 if( !OpenClipboard(NULL) )
7733 HGLOBAL TextHandle = GlobalAlloc(GMEM_MOVEABLE, _String.length()+1);
7734 if( TextHandle==NULL )
7739 char *TextString = static_cast<char *>(GlobalLock(TextHandle));
7740 memcpy(TextString, _String.c_str(), _String.length());
7741 TextString[_String.length()] = '\0';
7742 GlobalUnlock(TextHandle);
7743 SetClipboardData(CF_TEXT, TextHandle);
7746 #elif defined ANT_UNIX
7748 if( g_TwMgr->m_CurrentXDisplay!=NULL )
7750 XSetSelectionOwner(g_TwMgr->m_CurrentXDisplay, XA_PRIMARY, None, CurrentTime);
7751 char *Text = new char[_String.length()+1];
7752 memcpy(Text, _String.c_str(), _String.length());
7753 Text[_String.length()] = '\0';
7754 XStoreBytes(g_TwMgr->m_CurrentXDisplay, Text, _String.length());
7764 // ---------------------------------------------------------------------------