1 /*
2 Copyright (C) 2005 David Kamphausen <david.kamphausen@web.de>
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17 */
18 #include <config.h>
19 
20 #include "PBar.hpp"
21 #include "Util.hpp"
22 #include "gui/ComponentFactory.hpp"
23 #include "gui/ComponentLoader.hpp"
24 #include "gui/XmlReader.hpp"
25 #include "gui/Paragraph.hpp"
26 #include "gui/Painter.hpp"
27 
28 LCPBar* LCPBarInstance = 0;
29 
LCPBar()30 LCPBar::LCPBar()
31 {
32     LCPBarInstance = this;
33 }
34 
~LCPBar()35 LCPBar::~LCPBar()
36 {
37     if(LCPBarInstance == this)
38         LCPBarInstance = 0;
39 }
40 
41 void
parse(XmlReader & reader)42 LCPBar::parse(XmlReader& reader)
43 {
44     XmlReader::AttributeIterator iter(reader);
45     while(iter.next()) {
46         const char* name = (const char*) iter.getName();
47         const char* value = (const char*) iter.getValue();
48 
49         if(parseAttribute(name, value)) {
50             continue;
51         } else {
52             std::cerr << "Unknown attribute '" << name
53                       << "' skipped in PBar.\n";
54         }
55     }
56 
57     Component* component = parseEmbeddedComponent(reader);
58     addChild(component);
59 
60     width = component->getWidth();
61     height = component->getHeight();
62 }
63 
64 // copied from old-gui
65 #define pbar_adjust_pop(diff) 2 * diff
66 #define pbar_adjust_tech(diff) diff > 0 ? diff / 4 + 1 : -((-diff+1)/ 2)
67 #define pbar_adjust_food(diff) diff > 0 ? diff / 2 + 1 : diff
68 #define pbar_adjust_jobs(diff) diff > 0 ? diff / 2 + 1 : diff
69 #define pbar_adjust_coal(diff) diff > 0 ? diff / 2 + 1 : diff
70 #define pbar_adjust_goods(diff) diff > 0 ? diff / 2 + 1 : diff
71 #define pbar_adjust_ore(diff) diff > 0 ? diff / 2 + 1 : diff
72 #define pbar_adjust_steel(diff) diff > 0 ? diff / 2 + 1 : diff
73 #define pbar_adjust_money(diff) diff  > 0 ? diff / 800 + 1 : diff / 400
74 
75 void
setValue(int num,int value,int diff)76 LCPBar::setValue(int num, int value, int diff)
77 {
78     std::ostringstream compname;
79     compname << "pbar_text" << (num+1);
80     Paragraph* p = getParagraph(*this, compname.str());
81 
82     std::ostringstream os;
83     os<<std::fixed;
84     os<<std::setprecision(1);
85     if(num==PTECH)
86     {
87         os<<value/10000.0;
88      }
89     else if(num==PMONEY)
90     {
91         if(abs(value)>=1000000000)
92             os<<value/1000000<<"M";
93         else if(abs(value)>1000000)
94             os<<value/1000000.0<<"M";
95         else if(abs(value)>1000)
96             os<<value/1000.0<<"K";
97         else
98             os<<value;
99     }
100     else
101         os<<value;
102 
103     if( diff != 0 ){
104         p->setText(os.str());
105     }
106     os.str("");
107     os<<"pbar_barview"<<(num+1);
108 
109     float sv=0;
110     switch(num)
111     {
112       case PPOP:
113         sv=pbar_adjust_pop(diff);
114         break;
115       case PTECH:
116         sv=pbar_adjust_tech(diff);
117         break;
118       case PFOOD:
119         sv=pbar_adjust_food(diff);break;
120       case PJOBS:
121         sv=pbar_adjust_jobs(diff);break;
122       case PCOAL:
123         sv=pbar_adjust_coal(diff);break;
124       case PGOODS:
125         sv=pbar_adjust_goods(diff);break;
126       case PORE:
127         sv=pbar_adjust_ore(diff);break;
128       case PSTEEL:
129         sv=pbar_adjust_steel(diff);break;
130       case PMONEY:
131         sv=pbar_adjust_money(diff);break;
132       };
133 
134     sv/=10.0;
135 
136 
137      if(sv>1.0)
138       sv=1.0;
139      if(sv<-1.0)
140       sv=-1.0;
141 
142     Component *c=findComponent(os.str()+"a");
143     if(c)
144     {
145       BarView *bv=dynamic_cast<BarView*>(c);
146       if(bv)
147       {
148         bv->setValue(sv);
149       }
150     }
151     c=findComponent(os.str()+"b");
152     if(c)
153     {
154       BarView *bv=dynamic_cast<BarView*>(c);
155       if(bv)
156       {
157         bv->setValue(sv);
158       }
159     }
160 
161 }
162 
163 ///////////////////////////////////////////////////////////////////////////////////////
164 // BarView
165 ///////////////////////////////////////////////////////////////////////////////////////
166 
BarView()167 BarView::BarView()
168 {
169 }
170 
~BarView()171 BarView::~BarView()
172 {
173 }
174 
175 void
parse(XmlReader & reader)176 BarView::parse(XmlReader& reader)
177 {
178     dir=true;
179     // parse attributes...
180     XmlReader::AttributeIterator iter(reader);
181     while(iter.next()) {
182         const char* name = (const char*) iter.getName();
183         const char* value = (const char*) iter.getValue();
184 
185         if(parseAttribute(name, value)) {
186             continue;
187         } else if(strcmp(name, "width") == 0) {
188             if(sscanf(value, "%f", &width) != 1) {
189                 std::stringstream msg;
190                 msg << "Couldn't parse width attribute (" << value << ").";
191                 throw std::runtime_error(msg.str());
192             }
193         } else if(strcmp(name, "height") == 0) {
194             if(sscanf(value, "%f", &height) != 1) {
195                 std::stringstream msg;
196                 msg << "Couldn't parse height attribute (" << value << ").";
197                 throw std::runtime_error(msg.str());
198             }
199         } else if(strcmp(name, "dir") == 0) {
200             if(strcmp(value,"1") == 0) {
201                 dir=true;
202             } else {
203                 dir=false;
204             }
205         } else {
206             std::cerr << "Unknown attribute '" << name
207                       << "' skipped in BarView.\n";
208         }
209     }
210     if(width <= 0 || height <= 0)
211         throw std::runtime_error("Width or Height invalid");
212     value=0.7;
213 }
214 
setValue(float v)215 void BarView::setValue(float v)
216 {
217     if(v>=-1.0 && v<=1.0)
218         value=v;
219 }
220 
draw(Painter & painter)221 void BarView::draw(Painter &painter)
222 {
223     painter.setFillColor(Color(0,0xAA,0,255));
224 
225     if((int)(width*value)>0 && dir) {
226         painter.fillRectangle(Rect2D(0,0,width*value,height));
227     } else if((int)(width*value)<0 && !dir) {
228         painter.setFillColor(Color(0xFF,0,0,255));
229         painter.fillRectangle(Rect2D(width-1+width*value,0,width-1,height));
230     }
231 }
232 
233 IMPLEMENT_COMPONENT_FACTORY(LCPBar);
234 IMPLEMENT_COMPONENT_FACTORY(BarView);
235