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