fix gPixmap ref, fix usage of gImage
[enigma2.git] / lib / gui / enumber.cpp
1 #include <lib/gui/enumber.h>
2 #include <lib/driver/rc.h>
3 #include <lib/gui/eskin.h>
4 #include <lib/gui/elabel.h>
5 #include <lib/gdi/fb.h>
6 #include <lib/gdi/grc.h>
7 #include <lib/gdi/font.h>
8 #include <lib/gui/guiactions.h>
9
10 void eNumber::unpack(__u32 l, int *t)
11 {
12         for (int i=0; i<4; i++)
13                 *t++=(l>>((3-i)*8))&0xFF;
14 }
15
16 void eNumber::pack(__u32 &l, int *t)
17 {
18         l=0;
19         for (int i=0; i<4; i++)
20                 l|=(*t++)<<((3-i)*8);
21 }
22
23 eRect eNumber::getNumberRect(int n)
24 {
25         if (deco_selected && have_focus)
26                 return eRect( deco_selected.borderLeft + n * space_selected, deco_selected.borderTop, dspace, crect_selected.height() );
27         else if (deco)
28                 return eRect( deco.borderLeft + n * dspace, deco.borderTop, dspace, crect.height() );
29         else
30                 return eRect( n * dspace, 0, dspace, height() );
31 }
32
33 void eNumber::redrawNumber(gPainter *p, int n, const eRect &area)
34 {
35         eRect pos =     getNumberRect(n);
36
37         if (!area.contains(pos) )
38                 return;
39
40         p->setForegroundColor((have_focus && n==active)?cursorB:normalB);
41         p->fill(pos);
42         p->setFont(font);
43
44         eString t;
45         if (flags & flagFillWithZeros || ( (flags & flagFixedNum) && n ))
46         {
47     eString s = "%0"+eString().setNum(maxdigits)+(base==10?"d":"X");
48                 const char* p = s.c_str();
49                 char* tmp = new char[10];
50                 strcpy( tmp, p );
51                 t.sprintf(tmp, number[n]);
52                 delete [] tmp;
53         }
54         else
55         {
56                 if (flags&flagHideInput)
57                         t="*";
58                 else if (base==10)
59                         t.sprintf("%d", number[n]);
60                 else if (base==0x10)
61                         t.sprintf("%X", number[n]);
62         }
63
64         if (!n && flags & flagPosNeg && neg)
65                 t="-"+t;
66
67         if (n && (flags & flagTime))
68                 t=":"+t;
69
70         else if (n && ( (flags & flagDrawPoints) || (flags & flagFixedNum)) )
71                 t="."+t;
72
73         p->setForegroundColor((have_focus && n==active)?cursorF:normalF);
74         p->setBackgroundColor((have_focus && n==active)?cursorB:normalB);
75
76         p->clip( pos );
77         if (!n && len==2 && ((flags & flagFixedNum) || (flags & flagTime)) ) // first element...
78         {
79                 eTextPara *para = new eTextPara( pos );
80                 para->setFont( font );
81                 para->renderString( t );
82                 para->realign( eTextPara::dirRight );
83                 p->renderPara( *para );
84                 para->destroy();
85         }
86         else
87                 p->renderText(pos, t);
88                 
89         p->clippop();
90 }
91
92 double eNumber::getFixedNum()
93 {
94         if (flags & flagFixedNum)
95         {
96                 if (flags&flagPosNeg && neg)
97                 {
98                         double d = -((double)number[0]+(double)number[1]/1000);
99                         eDebug("getFixedNum %lf", d);
100                         return d;
101                 }
102                 else
103                 {
104                         float d = (double)number[0]+(double)number[1]/1000;
105                         eDebug("getFixedNum %lf", d);
106                         return d;
107                 }
108         }
109         else
110                 return 0;
111 }
112
113 void eNumber::setFixedNum(double d)
114 {
115         eDebug("setFixedNum %lf", d);
116         if (flags & flagPosNeg)
117                 neg=d<0;
118         else
119                 neg=0;
120
121         d=fabs(d);
122
123         if (flags & flagFixedNum)
124         {
125                 number[0]=(int)d;
126                 number[1]=(int)round(( ( d - number[0] ) * 1000) );
127         }
128         else
129                 eDebug("eNumber bug... the Number %s is not a fixed Point number", name.c_str());
130 }
131
132 void eNumber::redrawWidget(gPainter *p, const eRect &area)
133 {
134         for (int i=0; i<len; i++)
135                 redrawNumber(p, i, area);
136
137         if (deco_selected && have_focus)
138                 deco_selected.drawDecoration(p, ePoint(width(), height()));
139         else if (deco)
140                 deco.drawDecoration(p, ePoint(width(), height()));
141 }
142
143 void eNumber::invalidateNum()
144 {
145         if ( have_focus && deco_selected )
146                 invalidate( crect_selected );
147         else if ( deco )
148                 invalidate( crect );
149         else
150                 invalidate();
151 }
152
153 int eNumber::eventHandler(const eWidgetEvent &event)
154 {
155 #ifndef DISABLE_LCD
156         if (LCDTmp)
157                 ((eNumber*) LCDTmp)->eventHandler(event);
158 #endif
159         switch (event.type)
160         {
161         case eWidgetEvent::changedSize:
162                 if (deco)
163                         dspace = (crect.width()) / len;
164                 else
165                         dspace = (size.width()) / len;  
166                 if (deco_selected)
167                         space_selected = (crect_selected.width()) / len;
168                 break;
169         case eWidgetEvent::evtAction:
170                 if ( len > 1 && event.action == &i_cursorActions->left)
171                 {
172                         int oldac=active;
173                         active--;
174                         invalidate(getNumberRect(oldac));
175                         if (active<0)
176                                 active=len-1;
177                         if (active!=oldac)
178                                 invalidate(getNumberRect(active));
179                         digit=0;
180                 } else if ( len > 1 && (event.action == &i_cursorActions->right) || (event.action == &i_cursorActions->ok))
181                 {
182                         int oldac=active;
183                         active++;
184                         invalidate(getNumberRect(oldac));
185                         if (active>=len)
186                         {
187                                 if (event.action == &i_cursorActions->ok)
188                                 /*emit*/ selected(number);
189                                 active=0;
190                         }
191                         if (active!=oldac)
192                                 invalidate(getNumberRect(active));
193                         digit=0;
194                 } else
195                                 break;
196                 return 1;
197         default:
198                 break;
199         }
200         return eDecoWidget::eventHandler(event);
201 }
202
203 // isactive is the digit (always in the first field )
204 // that ist active after get the first focus ! 
205
206 eNumber::eNumber(eWidget *parent, int _len, int _min, int _max, int _maxdigits, int *init, int isactive, eWidget* descr, int grabfocus, const char *deco)
207  :eDecoWidget(parent, grabfocus, deco ),
208         active(0), 
209         cursorB(eSkin::getActive()->queryScheme("global.selected.background")), 
210         cursorF(eSkin::getActive()->queryScheme("global.selected.foreground")), 
211         normalB(eSkin::getActive()->queryScheme("global.normal.background")),   
212         normalF(eSkin::getActive()->queryScheme("global.normal.foreground")),   
213         have_focus(0), digit(isactive), isactive(isactive), flags(0), descr(descr), tmpDescr(0),
214         neg(false)
215 {
216         setNumberOfFields(_len);
217         setLimits(_min, _max);
218         setMaximumDigits(_maxdigits);
219         setBase(10);
220         for (int i=0; init && i<len; i++)
221                 number[i]=init[i];
222         addActionMap(&i_cursorActions->map);
223 }                 
224              
225 eNumber::~eNumber()
226 {
227 }
228
229 int eNumber::keyDown(int key)
230 {
231 #ifndef DISABLE_LCD
232         if (LCDTmp)
233                 ((eNumber*) LCDTmp)->keyDown(key);
234 #endif
235         switch (key)
236         {
237         case eRCInput::RC_0 ... eRCInput::RC_9:
238         {
239                 int nn=(digit!=0)?number[active]*10:0;
240                 nn+=key-eRCInput::RC_0;
241                 if (flags & flagTime)
242                 {
243                         if ( active )
244                                 max = 59;
245                         else
246                                 max = 23;
247                 }
248                 else if (flags & flagFixedNum)
249                 {
250                         if (active)
251                                 max=999;
252                         else
253                                 max=oldmax;
254                 }
255                 if (nn>=min && nn<=max)
256                 {
257                         number[active]=nn;
258                         invalidate(getNumberRect(active));
259                         digit++;
260                         if ((digit>=maxdigits) || (nn==0))
261                         {        
262                                 active++;
263                                 invalidate(getNumberRect(active-1));
264                                 digit=0;
265                                 /*emit*/ numberChanged();
266                                 if (active>=len)
267                                 {
268                                         /*emit*/ selected(number);
269                                         active=0;
270                                 }
271                                 else
272                                         invalidate(getNumberRect(active));
273                         }
274                 }
275                 break;
276
277         break;
278         }
279         case eRCInput::RC_PLUS:
280                 if (flags & flagPosNeg && neg )
281                 {
282                         neg=false;
283                         invalidate(getNumberRect(0));
284                 }
285         break;
286
287         case eRCInput::RC_MINUS:
288                 if (flags & flagPosNeg && !neg )
289                 {
290                         neg=true;
291                         invalidate(getNumberRect(0));
292                 }
293         default:
294                 return 0;
295         }
296         return 1;
297 }
298
299 void eNumber::gotFocus()
300 {
301         have_focus++;
302         digit=isactive;
303
304   if (deco && deco_selected)
305                 invalidate();
306         else
307                 invalidate(getNumberRect(active));
308
309 #ifndef DISABLE_LCD
310         if (parent && parent->LCDElement)  // detect if LCD Avail
311         {
312                 LCDTmp = new eNumber(parent->LCDElement, len, min, max, maxdigits, &(number[0]), isactive, 0, 0);
313                 LCDTmp->hide();
314                 ((eNumber*)LCDTmp)->setFlags(flags);
315                 eSize s = parent->LCDElement->getSize();
316
317                 if (descr)
318                 {
319                         LCDTmp->move(ePoint(0,s.height()/2));
320                         LCDTmp->resize(eSize(s.width(), s.height()/2));
321                         tmpDescr = new eLabel(parent->LCDElement);
322                         tmpDescr->hide();
323                         tmpDescr->move(ePoint(0,0));
324                         tmpDescr->resize(eSize(s.width(), s.height()/2));
325                         tmpDescr->setText(descr->getText());
326                         tmpDescr->show();
327                 }
328                 else
329                 {
330                         LCDTmp->resize(s);
331                         LCDTmp->move(ePoint(0,0));
332                 }
333                 ((eNumber*)LCDTmp)->digit=digit;
334                 ((eNumber*)LCDTmp)->active=active;
335                 ((eNumber*)LCDTmp)->normalF=255;
336                 ((eNumber*)LCDTmp)->normalB=0;
337                 ((eNumber*)LCDTmp)->cursorF=0;
338                 ((eNumber*)LCDTmp)->cursorB=255;
339                 ((eNumber*)LCDTmp)->have_focus=1;
340                 LCDTmp->show();
341         }
342         #endif //DISABLE_LCD
343 }
344
345 void eNumber::lostFocus()
346 {
347 #ifndef DISABLE_LCD
348         if (LCDTmp)
349         {
350                 delete LCDTmp;
351                 LCDTmp=0;
352                 if (tmpDescr)
353                 {
354                         delete tmpDescr;
355                         tmpDescr=0;
356                 }
357         }
358 #endif
359         have_focus--;
360
361         if (deco && deco_selected)
362                 invalidate();
363         else
364                 invalidate(getNumberRect(active));
365         isactive=0;
366 }
367
368 void eNumber::setNumber(int f, int n)
369 {
370         if (flags & flagPosNeg)
371         {
372                 if(!f && n<0)
373                         neg=true;
374                 else
375                         neg=false;
376         }
377         else
378                 neg=false;
379
380         if ((f>=0) && (f<len))
381                 number[f]=abs(n);
382
383         invalidate(getNumberRect(f));
384 }
385
386 void eNumber::setLimits(int _min, int _max)
387 {
388         min=_min;
389         max=_max;
390         oldmax=max;
391 }
392
393 void eNumber::setNumberOfFields(int n)
394 {
395         len=n;
396 }
397
398 void eNumber::setMaximumDigits(int n)
399 {
400         if (n > 16)
401                 n=16;
402         maxdigits=n;
403         if (digit >= maxdigits)
404                 digit=0;
405 }
406
407 void eNumber::setFlags(int _flags)
408 {
409   if (flags&flagFixedNum)
410                 len=2;
411                 
412         flags=_flags;
413 }
414
415 void eNumber::setBase(int _base)
416 {
417         base=_base;
418 }
419
420 void eNumber::setNumber(int n)
421 {
422         if ( flags&flagPosNeg )
423                 neg = n < 0;
424         else
425                 neg=0;
426
427         if( len == 1 )
428                 number[0]=abs(n);
429         else
430                 for (int i=len-1; i>=0; --i)
431                 {
432                         number[i]=n%base;
433                         n/=base;
434                 }
435         invalidateNum();
436 }
437
438 int eNumber::getNumber()
439 {
440         int n=0;
441         for (int i=0; i<len; i++)
442         {
443                 n*=base;
444                 n+=number[i];
445         }
446         return flags&flagPosNeg && neg ? -n : n;
447 }