]> git.vomp.tv Git - vompclient.git/blob - wtabbar.cc
Windows fixes
[vompclient.git] / wtabbar.cc
1 /*
2     Copyright 2004-2005 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "wtabbar.h"
22 #include "surface.h"
23 #include "input.h"
24 #include "wbutton.h"
25 #include "colour.h"
26
27 WTabBar::WTabBar()
28 {
29   buttonBarActive = true;
30   visiblePane = 0;
31   setBackgroundColour(DrawStyle::TABVIEWBACKGROUND);
32   
33   symbolLeft.setPosition(0, 4);
34   symbolLeft.nextColour = DrawStyle::BUTTONBACKGROUND;
35   symbolLeft.nextSymbol = WSymbol::LEFTARROW;
36   add(&symbolLeft);
37
38   symbolRight.setPosition(0, 4); // will be reset in addtab
39   symbolRight.nextColour = DrawStyle::BUTTONBACKGROUND;
40   symbolRight.nextSymbol = WSymbol::RIGHTARROW;
41   add(&symbolRight);
42 }
43
44 WTabBar::~WTabBar()
45 {
46   for (UINT i = 0; i < tabs.size(); i++)
47   {
48     delete tabs[i].button;
49     delete tabs[i].pane; //moved from vopts MR
50   }
51 }
52
53 void WTabBar::addTab(const char* name, Boxx* boxx)
54 {
55   TabDetails td;
56   td.name = name;
57   td.nameWidth = 0;
58   
59   for(UINT i = 0; i < strlen(name); i++)
60   {
61     td.nameWidth += static_cast<UINT>(charWidth(name[i]));
62   }
63
64   UINT newButtonX = 22;
65   for(UINT i = 0; i < tabs.size(); i++) newButtonX += tabs[i].button->getWidth() + 10;
66
67   WButton* newButton = new WButton();
68   newButton->setText(name);
69   newButton->setPosition(newButtonX, 2);
70   newButton->setSize(td.nameWidth + 6, getFontHeight());
71   if ((newButtonX + newButton->getWidth()) > (getWidth() - 22)) newButton->setVisible(false);
72   add(newButton);
73     
74   boxx->setPosition(0, 34);
75   boxx->setSize(getWidth(), getHeight()-34);
76   add(boxx);
77
78   td.button = newButton;
79   td.pane = boxx;
80   tabs.push_back(td);
81     
82   if (tabs.size() == 1)
83   {
84     newButton->setActive(true);
85     boxx->setVisible(true);
86   }
87   else
88   {
89     newButton->setActive(false);
90     boxx->setVisible(false);
91     symbolRight.nextColour = DrawStyle::SELECTHIGHLIGHT;  // if this is the 2nd+ tab, ensure right arrow goes active
92   }
93
94   // WTabbar doesn't know its width during the constructor
95   // So this is moved to here for now
96   symbolRight.setPosition(getWidth() - 28, 4);
97 }
98
99 int WTabBar::handleCommand(int command)
100 {
101   // This returns 0 for not handled, and 1 for handled and please-update-me, 2 for handled-no-update
102
103   // if the focus is in a pane, send the command there
104   if (!buttonBarActive)
105   {
106     // Send the command to the pane
107     // Return code should be:
108       // 0 - not handled
109       // 1 - handled - stop command here
110       // 4 - handled - pane is returning control to here
111           // 5 - activate button bar and let button process the call, this for simple up and down scroll views
112       // FIXME standardise these
113       
114     int paneRetCode = tabs[visiblePane].pane->handleCommand(command);
115     if (paneRetCode == 0)
116     {
117       return 0;
118     }
119     else if (paneRetCode == 1)
120     {
121       draw();
122       return 1;
123     }
124     else if (paneRetCode == 4)
125     {
126       buttonBarActive = true;
127       tabs[visiblePane].button->setActive(true);      
128       if (visiblePane != 0) symbolLeft.nextColour = DrawStyle::SELECTHIGHLIGHT;
129       if (visiblePane != tabs.size() - 1) symbolRight.nextColour = DrawStyle::SELECTHIGHLIGHT;
130       draw();
131       return 1;
132     } else if (paneRetCode == 5)
133     {
134         buttonBarActive = true;
135         tabs[visiblePane].button->setActive(true);
136         if (visiblePane != 0) symbolLeft.nextColour = DrawStyle::SELECTHIGHLIGHT;
137         if (visiblePane != tabs.size() - 1) symbolRight.nextColour = DrawStyle::SELECTHIGHLIGHT;
138         draw();
139         // no return!
140     }
141   }
142
143   if (buttonBarActive)
144   {
145     switch(command)
146     {
147       case Input::LEFT:
148       {
149         if (!left()) return 2;
150         draw();
151         return 1;
152       }
153       case Input::RIGHT:
154       {
155         if (!right()) return 2;
156         draw();
157         return 1;
158       }
159       case Input::UP:
160       case Input::DOWN:
161       {
162         int handleResult = tabs[visiblePane].pane->handleCommand(command);
163         // A WOptionPane will accept control being passed into it from inactive, up or down (== 1).
164         // A WTextBox will only accept control if it will scroll (== 1). It will refuse if not (== 4).
165
166         if (handleResult == 1)
167         {
168           buttonBarActive = false;
169           tabs[visiblePane].button->dim();
170           symbolLeft.nextColour = DrawStyle::BUTTONBACKGROUND;
171           symbolRight.nextColour = DrawStyle::BUTTONBACKGROUND;
172           draw();
173           return 1;
174         }
175         else if (handleResult == 4)
176         {
177           // Do nothing.
178           return 2;
179         }
180         else
181         {
182           Log::getInstance()->log("WTabBar", Log::ERR, "Up/Down client returned not 1 or 4");
183         }
184       }
185     }  
186   }
187   return 0;  
188 }  
189
190 // When there are too many tabs to display simultaneously, extend this to shift the tabs left and right
191
192 bool WTabBar::left()
193 {
194   if (visiblePane == 0) return false;
195   tabs[visiblePane].button->setActive(false);
196   tabs[visiblePane].pane->setVisible(false);
197   --visiblePane;
198   tabs[visiblePane].button->setActive(true);
199   tabs[visiblePane].pane->setVisible(true);
200
201   if (visiblePane == 0) symbolLeft.nextColour = DrawStyle::BUTTONBACKGROUND;
202   symbolRight.nextColour = DrawStyle::SELECTHIGHLIGHT;
203
204   // Move the buttons..
205   if (tabs[visiblePane].button->getVisible() == false)
206   {
207     tabs[visiblePane].button->setVisible(true);
208     // We have gone << past the last visible button
209     UINT newButtonX = 22;
210     UINT j;
211     for(j = visiblePane; j < tabs.size(); j++) // start with the button just uncovered
212     {
213       if ((newButtonX + tabs[j].button->getWidth()) > (getWidth() - 22)) break; // this one too big.
214       tabs[j].button->setPosition(newButtonX, 2);
215       newButtonX += tabs[j].button->getWidth() + 10;
216     }
217     for(; j < tabs.size(); j++) // hide the rest
218     {
219       tabs[j].button->setVisible(false);
220     }
221   }
222
223   return true;
224 }
225
226 bool WTabBar::right()
227 {
228   if (visiblePane == tabs.size() - 1) return false;
229   tabs[visiblePane].button->setActive(false);
230   tabs[visiblePane].pane->setVisible(false);
231   ++visiblePane;
232   tabs[visiblePane].button->setActive(true);
233   tabs[visiblePane].pane->setVisible(true);
234   
235   if (visiblePane == tabs.size() - 1) symbolRight.nextColour = DrawStyle::BUTTONBACKGROUND;
236   symbolLeft.nextColour = DrawStyle::SELECTHIGHLIGHT;
237
238   // Move the buttons..
239   if (tabs[visiblePane].button->getVisible() == false)
240   {
241     tabs[visiblePane].button->setVisible(true);
242     // We have gone >> past the last visible button
243     // Move all buttons left, but need to work out which one to finally display as first on the left
244     UINT displayWidth = getWidth() - 44;
245     UINT widthSum = tabs[visiblePane].button->getWidth(); // start with width of newly shown button (on the right)
246     int startWith = 0;
247     int i;
248     for(i = visiblePane - 1; i >= 0; i--)
249     {
250       widthSum += tabs[i].button->getWidth() + 10; // add on width needed to display also the previous button
251       if (widthSum > displayWidth) // then it's too much
252       {
253         startWith = i + 1;
254         break;
255       }
256     }
257     
258     for(i = 0; i < startWith; i++) // For each button to the left of startWith...
259     {
260       tabs[i].button->setVisible(false);
261     }
262     
263     UINT newButtonX = 22;
264     for(UINT j = startWith; j <= visiblePane; j++) // startWith -> the one we just uncovered
265     {
266       tabs[j].button->setPosition(newButtonX, 2);
267       newButtonX += tabs[j].button->getWidth() + 10;
268     }      
269   }
270   
271   return true;
272 }
273
274 bool WTabBar::mouseMove(int x, int y) {
275     if (tabs[visiblePane].pane->mouseMove(x,y)) {
276         if (buttonBarActive){
277             buttonBarActive = false;
278             tabs[visiblePane].button->dim();
279             symbolLeft.nextColour = DrawStyle::BUTTONBACKGROUND;
280             symbolRight.nextColour = DrawStyle::BUTTONBACKGROUND;
281             
282         }
283         draw();
284         return true;
285     }
286     return false;
287 }
288
289 bool WTabBar::mouseAndroidScroll(int x, int y, int sx, int sy) {
290         if (tabs[visiblePane].pane->mouseAndroidScroll(x, y,sx,sy)) {
291                 draw();
292                 return true;
293         }
294         return false;
295 }
296
297 bool WTabBar::mouseLBDOWN(int x, int y) {
298     UINT i;
299     for (i=0;i<tabs.size();i++) {
300         if (tabs[i].button->getVisible()) {
301             if (tabs[i].button->mouseMove(x,y)) {
302                 tabs[visiblePane].button->setActive(false);
303                 tabs[visiblePane].pane->setVisible(false);
304                 tabs[visiblePane].pane->deactivateAllControls();
305                 visiblePane=i;
306                 tabs[visiblePane].button->setActive(true);
307                 tabs[visiblePane].pane->setVisible(true);
308                 tabs[visiblePane].pane->deactivateAllControls();
309                 buttonBarActive = true;
310                 draw();
311                 return true;
312             }
313         }
314     }
315     if (tabs[visiblePane].pane->mouseLBDOWN(x,y)) {
316         buttonBarActive = false;
317         tabs[visiblePane].button->dim();
318         symbolLeft.nextColour = DrawStyle::BUTTONBACKGROUND;
319         symbolRight.nextColour = DrawStyle::BUTTONBACKGROUND;
320         draw();
321         return true;
322     }
323     if (symbolLeft.mouseLBDOWN(x,y)) {
324         left();
325         draw();
326         return true;
327     }
328     if (symbolRight.mouseLBDOWN(x,y)) {
329         right();
330         draw();
331         return true;
332     }
333     return false;
334 }
335
336 void WTabBar::activateFocus(bool active)
337 {
338         if (active)
339         {
340                 tabs[visiblePane].button->setActive(true);
341                 buttonBarActive = true;
342
343         } else {
344                 tabs[visiblePane].button->setActive(false);
345                 buttonBarActive = false;
346
347         }
348 }
349