Merge "Move key grab implementation to window" into devel/master
[platform/core/uifw/dali-adaptor.git] / dali / internal / network / common / automation.cpp
1
2 /*
3  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 // CLASS HEADER
20 #include <dali/internal/network/common/automation.h>
21
22 // EXTERNAL INCLUDES
23 #include <sstream>
24 #include <iomanip>
25 #include <stdio.h>
26 #include <dali/public-api/dali-core.h>
27 #include <dali/integration-api/debug.h>
28
29
30 namespace  // un-named namespace
31 {
32
33 const unsigned int MAX_SET_PROPERTY_STRING_LENGTH = 256; ///< maximum length of a set property command
34
35 class JsonPropertyValue
36 {
37 public:
38   JsonPropertyValue( const std::string& str )
39   {
40     std::size_t strLength = str.length();
41
42     mString.reserve( strLength );
43     for( std::size_t i = 0; i < strLength; ++i )
44     {
45       const char c = str[i];
46       if( (c != '[') && c != ']')
47       {
48         mString.push_back( c );
49       }
50     }
51
52   }
53   std::string GetString() const
54   {
55     return mString;
56   }
57   float GetFloat() const
58   {
59     return atof( mString.c_str() );
60   }
61   int GetInt()
62   {
63     return atoi( mString.c_str() );
64   }
65   bool GetBoolean()
66   {
67     return (GetInt() != 0);
68   }
69
70   Dali::Vector2 GetVector2()
71   {
72     Dali::Vector2 vec2;
73
74     int count = sscanf( mString.c_str(),"%f,%f",&vec2.x,&vec2.y );
75     if( count != 2 )
76     {
77       DALI_LOG_ERROR("Bad format\n");
78     }
79     return vec2;
80   }
81
82   Dali::Vector3 GetVector3()
83   {
84     Dali::Vector3 vec3;
85
86     int count = sscanf( mString.c_str(),"%f,%f,%f",&vec3.x,&vec3.y,&vec3.z );
87     if( count != 3 )
88     {
89       DALI_LOG_ERROR("Bad format\n");
90     }
91     return vec3;
92   }
93
94   Dali::Vector4 GetVector4()
95   {
96     Dali::Vector4 vec4;
97
98     int count = sscanf( mString.c_str(),"%f,%f,%f,%f", &vec4.x, &vec4.y, &vec4.z, &vec4.w );
99     if( count != 4 )
100     {
101       DALI_LOG_ERROR("Bad format\n");
102     }
103     return vec4;
104   }
105
106 private:
107   std::string mString;
108
109 };
110
111 void SetProperty( Dali::Handle handle, int propertyId, JsonPropertyValue& propertyValue )
112 {
113   Dali::Property::Type type = handle.GetPropertyType( propertyId );
114   switch( type )
115   {
116   case Dali::Property::FLOAT:
117   {
118     float val = propertyValue.GetFloat();
119     handle.SetProperty( propertyId, Dali::Property::Value( val ) );
120     break;
121   }
122   case Dali::Property::INTEGER:
123   {
124     int val = propertyValue.GetInt();
125     handle.SetProperty( propertyId, Dali::Property::Value( val ) );
126     break;
127   }
128   case Dali::Property::BOOLEAN:
129   {
130     bool val = propertyValue.GetBoolean();
131     handle.SetProperty( propertyId, Dali::Property::Value( val ) );
132     break;
133   }
134   case Dali::Property::STRING:
135   {
136     std::string str = propertyValue.GetString();
137     handle.SetProperty( propertyId, Dali::Property::Value( str ) );
138     break;
139   }
140   case Dali::Property::VECTOR2:
141   {
142     Dali::Vector2 val = propertyValue.GetVector2();
143     handle.SetProperty( propertyId, Dali::Property::Value( val ) );
144     break;
145   }
146   case Dali::Property::VECTOR3:
147   {
148     Dali::Vector3 val = propertyValue.GetVector3();
149     handle.SetProperty( propertyId, Dali::Property::Value( val ) );
150     break;
151   }
152   case Dali::Property::VECTOR4:
153   {
154     Dali::Vector4 val = propertyValue.GetVector4();
155     handle.SetProperty( propertyId, Dali::Property::Value( val ) );
156     break;
157   }
158   default:
159   {
160     break;
161   }
162   }
163 }
164
165 int SetProperties( const std::string& setPropertyMessage )
166 {
167   std::istringstream iss( setPropertyMessage );
168   std::string token;
169   getline( iss, token, '|' ); // swallow command name
170   while( getline( iss, token, '|' ) )
171   {
172     std::string actorId, propName, propValue;
173     if( token.compare( "---" ) != 0 )
174     {
175       std::istringstream propss( token );
176       getline( propss, actorId, ';' );
177       getline( propss, propName, ';' );
178       getline( propss, propValue );
179
180       Dali::Actor root = Dali::Stage::GetCurrent().GetRootLayer();
181       int id = atoi( actorId.c_str() );
182       Dali::Actor a = root.FindChildById( id );
183       if( a )
184       {
185         // lookup by name for custom properties
186         int propId = a.GetPropertyIndex( propName );
187         if( propId > 0 )
188         {
189           JsonPropertyValue pv( propValue );
190           SetProperty( a, propId, pv );
191         }
192
193       }
194     }
195   }
196
197   return 0;
198 }
199
200
201 }; //   un-named namespace
202
203 inline std::string Quote( const std::string& in )
204 {
205   return (std::string( "\"" ) + in + std::string( "\"" ));
206 }
207
208 template<class T>
209 std::string ToString( T i )
210 {
211   std::stringstream ss;
212   std::string s;
213   ss << i;
214   s = ss.str();
215
216   return s;
217 }
218
219 std::string GetPropertyValueString( Dali::Handle handle, int propertyIndex )
220 {
221   std::ostringstream valueStream;
222   Dali::Property::Value value = handle.GetProperty( propertyIndex );
223   valueStream << value;
224   std::string valueString = valueStream.str();
225
226   if( value.GetType() == Dali::Property::STRING )
227   {
228     // Escape the string (to ensure valid json)
229     // Write out quotes, escapes and control characters using unicode syntax \uXXXX
230     std::ostringstream escapedValue;
231     for( std::string::iterator c = valueString.begin() ; c != valueString.end(); ++c )
232     {
233       if( *c == '"' )
234       {
235         escapedValue << "\\\"";
236       }
237       else if( *c == '\\' )
238       {
239         escapedValue << "\\\\";
240       }
241       else if( '\x00' <= *c && *c <= '\x1f' )
242       {
243         escapedValue << "\\u" << std::hex << std::setw(4) << std::setfill('0') << int(*c);
244       }
245       else
246       {
247         escapedValue << *c;
248       }
249     }
250
251     valueString = escapedValue.str();
252   }
253   return valueString;
254 }
255
256 // currently rotations are output in Euler format ( may change)
257 void AppendPropertyNameAndValue( Dali::Handle handle, int propertyIndex, std::ostringstream& outputStream)
258 {
259   // get the property name and the value as a string
260   std::string propertyName( handle.GetPropertyName( propertyIndex ) );
261
262   // Apply quotes around the property name
263   outputStream << "\"" << propertyName << "\"" << ",";
264
265   // Convert value to a string
266   std::string valueString = GetPropertyValueString( handle, propertyIndex );
267
268   outputStream << "\"" << valueString << "\"";
269 }
270
271 void AppendRendererPropertyNameAndValue( Dali::Renderer renderer, int rendererIndex, const std::string& name, std::ostringstream& outputStream)
272 {
273   outputStream << ",[\"renderer[" << rendererIndex << "]." << name << "\"" << ",";
274   std::string valueString = GetPropertyValueString( renderer, renderer.GetPropertyIndex( name ) );
275   outputStream << "\"" << valueString << "\"]";
276 }
277
278 bool ExcludeProperty( int propIndex )
279 {
280   return (propIndex == Dali::Actor::Property::NAME    ||
281
282       // all of these are repeat properties of values in vectors....
283       // We don't really need these in the UI
284       propIndex == Dali::Actor::Property::ANCHOR_POINT_X || propIndex == Dali::Actor::Property::ANCHOR_POINT_Y || propIndex == Dali::Actor::Property::ANCHOR_POINT_Z || propIndex == Dali::Actor::Property::PARENT_ORIGIN_X
285       || propIndex == Dali::Actor::Property::PARENT_ORIGIN_Y || propIndex == Dali::Actor::Property::PARENT_ORIGIN_Z || propIndex == Dali::Actor::Property::COLOR_RED || propIndex == Dali::Actor::Property::COLOR_GREEN
286       || propIndex == Dali::Actor::Property::COLOR_BLUE || propIndex == Dali::Actor::Property::COLOR_ALPHA|| propIndex == Dali::Actor::Property::POSITION_X || propIndex == Dali::Actor::Property::POSITION_Y
287       || propIndex == Dali::Actor::Property::POSITION_Z|| propIndex == Dali::Actor::Property::SIZE_WIDTH|| propIndex == Dali::Actor::Property::SIZE_HEIGHT || propIndex == Dali::Actor::Property::SCALE_X || propIndex == Dali::Actor::Property::SCALE_Y
288       || propIndex == Dali::Actor::Property::SCALE_Z || propIndex == Dali::Actor::Property::SIZE_DEPTH);
289 }
290
291 std::string DumpJson( Dali::Actor actor, int level )
292 {
293   // All the information about this actor
294   std::ostringstream msg;
295   msg << "{ " << Quote( "Name" ) << " : " << Quote( actor.GetName() ) << ", " << Quote( "level" ) << " : " << level << ", " << Quote( "id" ) << " : " << actor.GetId() << ", " << Quote( "IsVisible" )
296       << " : " << actor.IsVisible() << ", " << Quote( "IsSensitive" ) << " : " << actor.IsSensitive();
297
298   msg << ", " << Quote( "properties" ) << ": [ ";
299
300   Dali::Property::IndexContainer indices;
301   actor.GetPropertyIndices( indices );
302
303   Dali::Property::IndexContainer::Iterator iter = indices.Begin();
304   int numCustom = 0;
305   for( ; iter != indices.End() ; iter++ )
306   {
307     int i = *iter;
308     if( !ExcludeProperty( i ) )
309     {
310       if( numCustom++ != 0 )
311       {
312         msg << ", ";
313       }
314       msg << "[";
315
316       AppendPropertyNameAndValue( actor, i,msg );
317
318       msg << "]";
319     }
320   }
321   if( actor.GetRendererCount() > 0 )
322   {
323     for( unsigned int i=0; i<actor.GetRendererCount(); ++i )
324     {
325       auto renderer = actor.GetRendererAt( i );
326       AppendRendererPropertyNameAndValue( renderer, i, "offset", msg );
327       AppendRendererPropertyNameAndValue( renderer, i, "size", msg );
328       AppendRendererPropertyNameAndValue( renderer, i, "offsetSizeMode", msg );
329       AppendRendererPropertyNameAndValue( renderer, i, "origin", msg );
330       AppendRendererPropertyNameAndValue( renderer, i, "anchorPoint", msg );
331     }
332   }
333
334   msg << "]";
335   msg << ", " << Quote( "children" ) << " : [ ";
336
337   // Recursively dump all the children as well
338   for( unsigned int i = 0 ; i < actor.GetChildCount() ; ++i )
339   {
340     if( i )
341     {
342       msg << " , ";
343     }
344     msg << DumpJson( actor.GetChildAt( i ), level + 1 );
345   }
346   msg << "] }";
347
348   return msg.str();
349 }
350
351 std::string GetActorTree()
352 {
353   Dali::Actor actor = Dali::Stage::GetCurrent().GetRootLayer();
354   std::string str = DumpJson( actor, 0 );
355   return str;
356 }
357 namespace Dali
358 {
359
360 namespace Internal
361 {
362
363 namespace Adaptor
364 {
365
366 namespace Automation
367 {
368
369 void SetProperty( const std::string& message )
370 {
371   // check the set property length is within range
372   if( message.length() > MAX_SET_PROPERTY_STRING_LENGTH )
373   {
374     DALI_LOG_ERROR("SetProperty message length too long, size = %ul\n", message.length());
375     return;
376   }
377
378   SetProperties( message );
379 }
380
381 void DumpScene( unsigned int clientId, ClientSendDataInterface* sendData )
382 {
383   char buf[32];
384   std::string json = GetActorTree();
385   int length = json.length();
386   snprintf( buf, 32, "%d\n", length );
387   std::string header( buf );
388   json = buf + json;
389   sendData->SendData( json.c_str(), json.length(), clientId );
390 }
391
392 } // namespace Automation
393
394 } // namespace Internal
395
396 } // namespace Adaptor
397
398 } // namespace Dali