Ticket #2589: no-cparser-GUI.diff
File no-cparser-GUI.diff, 15.3 KB (added by , 10 years ago) |
---|
-
source/gui/GUIbase.cpp
1 /* Copyright (C) 20 09Wildfire Games.1 /* Copyright (C) 2014 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 21 21 22 22 #include "precompiled.h" 23 23 24 #include <string> 25 24 #include "ps/CLogger.h" 26 25 #include "GUI.h" 27 26 28 27 //-------------------------------------------------------- … … 62 61 63 62 bool CClientArea::SetClientArea(const CStr& Value) 64 63 { 65 // This might lack incredible speed, but since all XML files 66 // are read at startup, reading 100 client areas will be 67 // negligible in the loading time. 64 /* ClientAreas contain a left, top, right, and bottom 65 * for example: "50%-150 10%+9 50%+150 10%+25" means 66 * the left edge is at 50% minus 150 pixels, the top 67 * edge is at 10% plus 9 pixels, the right edge is at 68 * 50% plus 150 pixels, and the bottom edge is at 10% 69 * plus 25 pixels. 70 * All four coordinates are required and can be 71 * defined only in pixels, only in percents, or some 72 * combination of both. 73 */ 68 74 69 // Setup parser to parse the value 70 71 // One of the four values: 72 // will give outputs like (in argument): 73 // (200) <== no percent, just the first $value 74 // (200) (percent) <== just the percent 75 // (200) (percent) (100) <== percent PLUS pixel 76 // (200) (percent) (-100) <== percent MINUS pixel 77 // (200) (percent) (100) (-100) <== Both PLUS and MINUS are used, INVALID 78 /* 79 string one_value = "_[-_$arg(_minus)]$value[$arg(percent)%_[+_$value]_[-_$arg(_minus)$value]_]"; 80 string four_values = one_value + "$arg(delim)" + 81 one_value + "$arg(delim)" + 82 one_value + "$arg(delim)" + 83 one_value + "$arg(delim)_"; // it's easier to just end with another delimiter 84 */ 85 // Don't use the above strings, because they make this code go very slowly 86 const char* four_values = 87 "_[-_$arg(_minus)]$value[$arg(percent)%_[+_$value]_[-_$arg(_minus)$value]_]" "$arg(delim)" 88 "_[-_$arg(_minus)]$value[$arg(percent)%_[+_$value]_[-_$arg(_minus)$value]_]" "$arg(delim)" 89 "_[-_$arg(_minus)]$value[$arg(percent)%_[+_$value]_[-_$arg(_minus)$value]_]" "$arg(delim)" 90 "_[-_$arg(_minus)]$value[$arg(percent)%_[+_$value]_[-_$arg(_minus)$value]_]" "$arg(delim)" 91 "_"; 92 CParser& parser (CParserCache::Get(four_values)); 93 94 CParserLine line; 95 line.ParseString(parser, Value); 96 97 if (!line.m_ParseOK) 98 return false; 99 100 int arg_count[4] = {0,0,0,0}; // argument counts for the four values 101 int arg_start[4] = {0,0,0,0}; // location of first argument, [0] is always 0 102 103 // Divide into the four piles (delimiter is an argument named "delim") 104 for (int i=0, valuenr=0; i<(int)line.GetArgCount(); ++i) 75 // Check the input is only numeric 76 const char* input = Value.c_str(); 77 CStr buffer = ""; 78 unsigned int coord = 0; 79 float pixels[4] = {0, 0, 0, 0}; 80 float percents[4] = {0, 0, 0, 0}; 81 for (unsigned int i = 0; i < Value.length(); i++) 105 82 { 106 std::string str; 107 line.GetArgString(i, str); 108 if (str == "delim") 83 switch (input[i]) 109 84 { 110 if (valuenr==0) 111 { 112 arg_count[0] = i; 113 arg_start[1] = i+1; 114 } 115 else 116 { 117 if (valuenr!=3) 118 { 119 ENSURE(valuenr <= 2); 120 arg_start[valuenr+1] = i+1; 121 arg_count[valuenr] = arg_start[valuenr+1] - arg_start[valuenr] - 1; 122 } 123 else 124 arg_count[3] = (int)line.GetArgCount() - arg_start[valuenr] - 1; 125 } 126 127 ++valuenr; 85 case '.': 86 case '0': 87 case '1': 88 case '2': 89 case '3': 90 case '4': 91 case '5': 92 case '6': 93 case '7': 94 case '8': 95 case '9': 96 buffer.push_back(input[i]); 97 break; 98 case '+': 99 pixels[coord] += buffer.ToFloat(); 100 buffer = "+"; 101 break; 102 case '-': 103 pixels[coord] += buffer.ToFloat(); 104 buffer = "-"; 105 break; 106 case '%': 107 percents[coord] += buffer.ToFloat(); 108 buffer = ""; 109 break; 110 case ' ': 111 pixels[coord] += buffer.ToFloat(); 112 buffer = ""; 113 coord++; 114 break; 115 default: 116 LOGWARNING(L"ClientArea definitions may only contain numerics. Your input: '%s'", Value.c_str()); 117 return false; 128 118 } 119 if (coord > 3) 120 { 121 LOGWARNING(L"Too many CClientArea parameters (4 max). Your input: '%s'", Value.c_str()); 122 return false; 123 } 129 124 } 130 125 131 // Iterate argument 132 133 // This is the scheme: 134 // 1 argument = Just pixel value 135 // 2 arguments = Just percent value 136 // 3 arguments = percent and pixel 137 // 4 arguments = INVALID 138 139 // Default to 0 140 float values[4][2] = {{0.f,0.f},{0.f,0.f},{0.f,0.f},{0.f,0.f}}; 141 for (int v=0; v<4; ++v) 126 if (coord < 3) 142 127 { 143 if (arg_count[v] == 1) 144 { 145 std::string str; 146 line.GetArgString(arg_start[v], str); 128 LOGWARNING(L"Too few CClientArea parameters (4 min). Your input: '%s'", Value.c_str()); 129 return false; 130 } 147 131 148 if (!line.GetArgFloat(arg_start[v], values[v][1])) 149 return false; 150 } 151 else 152 if (arg_count[v] == 2) 153 { 154 if (!line.GetArgFloat(arg_start[v], values[v][0])) 155 return false; 156 } 157 else 158 if (arg_count[v] == 3) 159 { 160 if (!line.GetArgFloat(arg_start[v], values[v][0]) || 161 !line.GetArgFloat(arg_start[v]+2, values[v][1])) 162 return false; 132 // Now that we're at the end of the string, flush the remaining buffer. 133 pixels[coord] += buffer.ToFloat(); 163 134 164 } 165 else return false; 166 } 167 168 // Now store the values[][] in the right place 169 pixel.left = values[0][1]; 170 pixel.top = values[1][1]; 171 pixel.right = values[2][1]; 172 pixel.bottom = values[3][1]; 173 percent.left = values[0][0]; 174 percent.top = values[1][0]; 175 percent.right = values[2][0]; 176 percent.bottom = values[3][0]; 135 // Now store the coords in the right place 136 pixel.left = pixels[0]; 137 pixel.top = pixels[1]; 138 pixel.right = pixels[2]; 139 pixel.bottom = pixels[3]; 140 percent.left = percents[0]; 141 percent.top = percents[1]; 142 percent.right = percents[2]; 143 percent.bottom = percents[3]; 177 144 return true; 178 145 } 179 146 -
source/gui/GUIutil.cpp
1 /* Copyright (C) 201 2Wildfire Games.1 /* Copyright (C) 2014 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 23 23 #include "GUI.h" 24 24 #include "GUIManager.h" 25 25 #include "maths/Matrix3D.h" 26 #include "ps/Parser.h"27 26 28 27 extern int g_xres, g_yres; 29 28 … … 61 60 template <> 62 61 bool __ParseString<CRect>(const CStrW& Value, CRect &Output) 63 62 { 64 // Use the parser to parse the values65 CParser& parser (CParserCache::Get("_$value_$value_$value_$value_"));66 67 CParserLine line;68 line.ParseString(parser, Value.ToUTF8());69 if (!line.m_ParseOK)63 const unsigned int NUM_COORDS = 4; 64 float coords[NUM_COORDS]; 65 std::wstringstream stream; 66 stream.str(Value); 67 // Parse each coordinate 68 for (unsigned int i = 0; i < NUM_COORDS; i++) 70 69 { 71 // Parsing failed 72 return false; 73 } 74 float values[4]; 75 for (int i=0; i<4; ++i) 76 { 77 if (!line.GetArgFloat(i, values[i])) 70 if (stream.eof()) 78 71 { 79 // Parsing failed72 LOGWARNING(L"Too few CRect parameters (min %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str()); 80 73 return false; 81 74 } 75 stream >> coords[i]; 76 if ((stream.rdstate() & std::wstringstream::failbit) != 0) 77 { 78 LOGWARNING(L"Unable to parse CRect parameters. Your input: '%s'", Value.ToUTF8().c_str()); 79 return false; 80 } 82 81 } 83 82 83 if (!stream.eof()) 84 { 85 LOGWARNING(L"Too many CRect parameters (max %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str()); 86 return false; 87 } 88 84 89 // Finally the rectangle values 85 Output = CRect(values[0], values[1], values[2], values[3]); 90 Output = CRect(coords[0], coords[1], coords[2], coords[3]); 91 86 92 return true; 87 93 } 88 94 … … 119 125 template <> 120 126 bool __ParseString<CSize>(const CStrW& Value, CSize &Output) 121 127 { 122 // Use the parser to parse the values123 CParser& parser (CParserCache::Get("_$value_$value_"));124 125 CParserLine line;126 line.ParseString(parser, Value.ToUTF8());127 if (!line.m_ParseOK)128 const unsigned int NUM_COORDS = 2; 129 float coords[NUM_COORDS]; 130 std::wstringstream stream; 131 stream.str(Value); 132 // Parse each coordinate 133 for (unsigned int i = 0; i < NUM_COORDS; i++) 128 134 { 129 // Parsing failed 130 return false; 135 if (stream.eof()) 136 { 137 LOGWARNING(L"Too few CSize parameters (min %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str()); 138 return false; 139 } 140 stream >> coords[i]; 141 if ((stream.rdstate() & std::wstringstream::failbit) != 0) 142 { 143 LOGWARNING(L"Unable to parse CSize parameters. Your input: '%s'", Value.ToUTF8().c_str()); 144 return false; 145 } 131 146 } 132 147 133 float x, y; 148 Output.cx = coords[0]; 149 Output.cy = coords[1]; 134 150 135 // x 136 if (!line.GetArgFloat(0, x)) 151 if (!stream.eof()) 137 152 { 138 // TODO Gee: Parsing failed153 LOGWARNING(L"Too many CSize parameters (max %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str()); 139 154 return false; 140 155 } 141 156 142 // y143 if (!line.GetArgFloat(1, y))144 {145 // TODO Gee: Parsing failed146 return false;147 }148 149 Output.cx = x;150 Output.cy = y;151 152 157 return true; 153 158 } 154 159 … … 155 160 template <> 156 161 bool __ParseString<CPos>(const CStrW& Value, CPos &Output) 157 162 { 158 CParser& parser (CParserCache::Get("_[-$arg(_minus)]$value_[-$arg(_minus)]$value_")); 163 const unsigned int NUM_COORDS = 2; 164 float coords[NUM_COORDS]; 165 std::wstringstream stream; 166 stream.str(Value); 167 // Parse each coordinate 168 for (unsigned int i = 0; i < NUM_COORDS; i++) 169 { 170 if (stream.eof()) 171 { 172 LOGWARNING(L"Too few CPos parameters (min %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str()); 173 return false; 174 } 175 stream >> coords[i]; 176 if ((stream.rdstate() & std::wstringstream::failbit) != 0) 177 { 178 LOGWARNING(L"Unable to parse CPos parameters. Your input: '%s'", Value.ToUTF8().c_str()); 179 return false; 180 } 181 } 159 182 160 CParserLine line; 161 line.ParseString(parser, Value.ToUTF8()); 162 if (!line.m_ParseOK) 163 return false; 183 Output.x = coords[0]; 184 Output.y = coords[1]; 164 185 165 float x, y; 166 if (!line.GetArgFloat(0, x)) 186 if (!stream.eof()) 187 { 188 LOGWARNING(L"Too many CPos parameters (max %i). Your input: '%s'", NUM_COORDS, Value.ToUTF8().c_str()); 167 189 return false; 168 if (!line.GetArgFloat(1, y)) 169 return false; 190 } 170 191 171 Output.x = x;172 Output.y = y;173 174 192 return true; 175 193 } 176 194 -
source/gui/GUIutil.h
37 37 // Includes / Compiler directives 38 38 //-------------------------------------------------------- 39 39 #include "GUIbase.h" 40 #include "ps/Parser.h"41 40 // TODO Gee: New 42 41 #include "ps/Overlay.h" 43 42 #include "CGUI.h" -
source/gui/IGUIObject.cpp
22 22 #include "precompiled.h" 23 23 #include "GUI.h" 24 24 25 #include "ps/Parser.h"26 27 25 #include "gui/scripting/JSInterface_IGUIObject.h" 28 26 #include "gui/scripting/JSInterface_GUITypes.h" 29 27 #include "scriptinterface/ScriptInterface.h" -
source/gui/tests/test_ParseString.h
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2014 Wildfire Games. 2 2 * This file is part of 0 A.D. 3 3 * 4 4 * 0 A.D. is free software: you can redistribute it and/or modify … … 18 18 #include "lib/self_test.h" 19 19 20 20 #include "gui/GUIbase.h" 21 #include "gui/GUIutil.h" 22 #include "ps/CLogger.h" 21 23 22 24 class TestGuiParseString : public CxxTest::TestSuite 23 25 { … … 24 26 public: 25 27 void test_clientarea() 26 28 { 29 TestLogger nolog; 27 30 CClientArea ca; 28 TS_ASSERT(ca.SetClientArea("0 1 2 3"));29 TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, 1, 2, 3), CRect(0, 0, 0, 0)));30 31 31 TS_ASSERT(ca.SetClientArea("5% 10%+1 20%-2 3")); 32 TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, 1, -2, 3), CRect(5, 10, 20, 0))); 32 // Test only pixels 33 TS_ASSERT(ca.SetClientArea("0.0 -10 20.0 -30")); 34 TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, -10, 20, -30), CRect(0, 0, 0, 0))); 33 35 34 TS_ASSERT(!ca.SetClientArea("0+5% 1 2 3")); 36 // Test only pixels, but with math 37 TS_ASSERT(ca.SetClientArea("0 -100-10+100 20+200-200 -30")); 38 TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, -10, 20, -30), CRect(0, 0, 0, 0))); 35 39 36 TS_ASSERT(!ca.SetClientArea("5%+10-10 1 2 3")); 40 // Test only percent 41 TS_ASSERT(ca.SetClientArea("-5% 10.0% -20% 30.0%")); 42 TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, 0, 0, 0), CRect(-5, 10, -20, 30))); 37 43 38 TS_ASSERT(ca.SetClientArea("5% 10%-1 -20%-2 3")); 39 TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, -1, -2, 3), CRect(5, 10, -20, 0))); 44 // Test only percent, but with math 45 TS_ASSERT(ca.SetClientArea("15%-5%-15% 10% -20% 30%+500%-500%")); 46 TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, 0, 0, 0), CRect(-5, 10, -20, 30))); 40 47 41 TS_ASSERT(!ca.SetClientArea("5% 10%+1 -20%-2 3")); // parser bug 48 // Test mixed 49 TS_ASSERT(ca.SetClientArea("5% -10 -20% 30")); 50 TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, -10, 0, 30), CRect(5, 0, -20, 0))); 51 52 // Test mixed with math 53 TS_ASSERT(ca.SetClientArea("5%+10%-10% 30%-10-30% 50-20%-50 30-100+100")); 54 TS_ASSERT_EQUALS(ca, CClientArea(CRect(0, -10, 0, 30), CRect(5, 0, -20, 0))); 55 56 // Test for fail with too many/few parameters 57 TS_ASSERT(!ca.SetClientArea("10 20 30 40 50")); 58 TS_ASSERT(!ca.SetClientArea("10 20 30")); 59 60 // Test for fail with garbage data 61 TS_ASSERT(!ca.SetClientArea("Hello world!")); 62 TS_ASSERT(!ca.SetClientArea("abc 123 xyz 789")); 63 TS_ASSERT(!ca.SetClientArea("300 wide, 400 high")); 42 64 } 65 66 void test_rect() 67 { 68 TestLogger nolog; 69 CRect test; 70 71 TS_ASSERT(__ParseString(CStrW(L"0.0 10.0 20.0 30.0"), test)); 72 TS_ASSERT_EQUALS(CRect(0.0, 10.0, 20.0, 30.0), test); 73 74 TS_ASSERT(!__ParseString(CStrW(L"0 10 20"), test)); 75 TS_ASSERT(!__ParseString(CStrW(L"0 10 20 30 40"), test)); 76 TS_ASSERT(!__ParseString(CStrW(L"0,0 10,0 20,0 30,0"), test)); 77 } 78 79 void test_size() 80 { 81 TestLogger nolog; 82 CSize test; 83 84 TS_ASSERT(__ParseString(CStrW(L"0.0 10.0"), test)); 85 TS_ASSERT_EQUALS(CSize(0.0, 10.0), test); 86 87 TS_ASSERT(!__ParseString(CStrW(L"0"), test)); 88 TS_ASSERT(!__ParseString(CStrW(L"0 10 20"), test)); 89 TS_ASSERT(!__ParseString(CStrW(L"0,0 10,0"), test)); 90 } 91 92 void test_pos() 93 { 94 TestLogger nolog; 95 CPos test; 96 97 TS_ASSERT(__ParseString(CStrW(L"0.0 10.0"), test)); 98 TS_ASSERT_EQUALS(CPos(0.0, 10.0), test); 99 100 TS_ASSERT(!__ParseString(CStrW(L"0"), test)); 101 TS_ASSERT(!__ParseString(CStrW(L"0 10 20"), test)); 102 TS_ASSERT(!__ParseString(CStrW(L"0,0 10,0"), test)); 103 } 43 104 }; -
binaries/data/mods/public/gui/session/session.xml
532 532 </object> 533 533 534 534 <object name="tradeStatistics" size="20 90 100%-20 168"> 535 <object name="landTraders" size="0 0 100%50%" type="text" style="ModernLabelText" text_align="left" ghost="true" />535 <object name="landTraders" size="0 0 100% 50%" type="text" style="ModernLabelText" text_align="left" ghost="true" /> 536 536 <object name="shipTraders" size="0 50% 100% 100%" type="text" style="ModernLabelText" text_align="left" ghost="true" /> 537 537 </object> 538 538