]> git.vomp.tv Git - vompclient-marten.git/blob - wtabbar.cc
0.2.7 readiness patches for Windows
[vompclient-marten.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "wtabbar.h"
22 #include "surface.h"
23 #include "remote.h"
24 #include "wbutton.h"
25 #include "colour.h"
26
27 WTabBar::WTabBar()
28 {
29   buttonBarActive = true;
30   visiblePane = 0;
31   setBackgroundColour(Colour::VIEWBACKGROUND);
32   
33   symbolLeft.setPosition(0, 4);
34   symbolLeft.nextColour = Colour::BUTTONBACKGROUND;
35   symbolLeft.nextSymbol = WSymbol::LEFTARROW;
36   add(&symbolLeft);
37
38   symbolRight.setPosition(getWidth() - 28, 4);
39   symbolRight.nextColour = Colour::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 += 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, Surface::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 = Colour::SELECTHIGHLIGHT;  // if this is the 2nd+ tab, ensure right arrow goes active
92   }
93 }
94
95 int WTabBar::handleCommand(int command)
96 {
97   // This returns 0 for not handled, and 1 for handled and please-update-me, 2 for handled-no-update
98
99   // if the focus is in a pane, send the command there
100   if (!buttonBarActive)
101   {
102     // Send the command to the pane
103     // Return code should be:
104       // 0 - not handled
105       // 1 - handled - stop command here
106       // 4 - handled - pane is returning control to here
107       // FIXME standardise these
108       
109     int paneRetCode = tabs[visiblePane].pane->handleCommand(command);
110     if (paneRetCode == 0)
111     {
112       return 0;
113     }
114     else if (paneRetCode == 1)
115     {
116       draw();
117       return 1;
118     }
119     else if (paneRetCode == 4)
120     {
121       buttonBarActive = true;
122       tabs[visiblePane].button->setActive(true);      
123       if (visiblePane != 0) symbolLeft.nextColour = Colour::SELECTHIGHLIGHT;
124       if (visiblePane != tabs.size() - 1) symbolRight.nextColour = Colour::SELECTHIGHLIGHT;
125       draw();
126       return 1;
127     }
128   }
129
130   if (buttonBarActive)
131   {
132     switch(command)
133     {
134       case Remote::DF_LEFT:
135       case Remote::LEFT:
136       {
137         if (!left()) return 2;
138         draw();
139         return 1;
140       }
141       case Remote::DF_RIGHT:
142       case Remote::RIGHT:
143       {
144         if (!right()) return 2;
145         draw();
146         return 1;
147       }
148       case Remote::DOWN:
149       case Remote::DF_DOWN:
150       {
151         buttonBarActive = false;
152         tabs[visiblePane].button->dim();
153         symbolLeft.nextColour = Colour::BUTTONBACKGROUND;
154         symbolRight.nextColour = Colour::BUTTONBACKGROUND;
155         if (tabs[visiblePane].pane->handleCommand(command) == 1) // shouldn't return anything else at this point?!
156         {
157           draw();
158           return 1;
159         }
160       }    
161     }  
162   }
163   return 0;  
164 }  
165
166 // When there are too many tabs to display simultaneously, extend this to shift the tabs left and right
167
168 bool WTabBar::left()
169 {
170   if (visiblePane == 0) return false;
171   tabs[visiblePane].button->setActive(false);
172   tabs[visiblePane].pane->setVisible(false);
173   --visiblePane;
174   tabs[visiblePane].button->setActive(true);
175   tabs[visiblePane].pane->setVisible(true);
176
177   if (visiblePane == 0) symbolLeft.nextColour = Colour::BUTTONBACKGROUND;
178   symbolRight.nextColour = Colour::SELECTHIGHLIGHT;
179
180   // Move the buttons..
181   if (tabs[visiblePane].button->getVisible() == false)
182   {
183     tabs[visiblePane].button->setVisible(true);
184     // We have gone << past the last visible button
185     UINT newButtonX = 22;
186     UINT j;
187     for(j = visiblePane; j < tabs.size(); j++) // start with the button just uncovered
188     {
189       if ((newButtonX + tabs[j].button->getWidth()) > (getWidth() - 22)) break; // this one too big.
190       tabs[j].button->setPosition(newButtonX, 2);
191       newButtonX += tabs[j].button->getWidth() + 10;
192     }
193     for(; j < tabs.size(); j++) // hide the rest
194     {
195       tabs[j].button->setVisible(false);
196     }
197   }
198
199   return true;
200 }
201
202 bool WTabBar::right()
203 {
204   if (visiblePane == tabs.size() - 1) return false;
205   tabs[visiblePane].button->setActive(false);
206   tabs[visiblePane].pane->setVisible(false);
207   ++visiblePane;
208   tabs[visiblePane].button->setActive(true);
209   tabs[visiblePane].pane->setVisible(true);
210   
211   if (visiblePane == tabs.size() - 1) symbolRight.nextColour = Colour::BUTTONBACKGROUND;
212   symbolLeft.nextColour = Colour::SELECTHIGHLIGHT;
213
214   // Move the buttons..
215   if (tabs[visiblePane].button->getVisible() == false)
216   {
217     tabs[visiblePane].button->setVisible(true);
218     // We have gone >> past the last visible button
219     // Move all buttons left, but need to work out which one to finally display as first on the left
220     UINT displayWidth = getWidth() - 44;
221     UINT widthSum = tabs[visiblePane].button->getWidth(); // start with width of newly shown button (on the right)
222     int startWith = 0;
223     int i;
224     for(i = visiblePane - 1; i >= 0; i--)
225     {
226       widthSum += tabs[i].button->getWidth() + 10; // add on width needed to display also the previous button
227       if (widthSum > displayWidth) // then it's too much
228       {
229         startWith = i + 1;
230         break;
231       }
232     }
233     
234     for(i = 0; i < startWith; i++) // For each button to the left of startWith...
235     {
236       tabs[i].button->setVisible(false);
237     }
238     
239     UINT newButtonX = 22;
240     for(UINT j = startWith; j <= visiblePane; j++) // startWith -> the one we just uncovered
241     {
242       tabs[j].button->setPosition(newButtonX, 2);
243       newButtonX += tabs[j].button->getWidth() + 10;
244     }      
245   }
246   
247   return true;
248 }
249
250 bool WTabBar::mouseMove(int x, int y) {
251     if (tabs[visiblePane].pane->mouseMove(x,y)) {
252         if (buttonBarActive){
253             buttonBarActive = false;
254             tabs[visiblePane].button->dim();
255             symbolLeft.nextColour = Colour::BUTTONBACKGROUND;
256             symbolRight.nextColour = Colour::BUTTONBACKGROUND;
257             
258         }
259         draw();
260         return true;
261     }
262     return false;
263 }
264
265 bool WTabBar::mouseLBDOWN(int x, int y) {
266     UINT i;
267     for (i=0;i<tabs.size();i++) {
268         if (tabs[i].button->getVisible()) {
269             if (tabs[i].button->mouseMove(x,y)) {
270                 tabs[visiblePane].button->setActive(false);
271                 tabs[visiblePane].pane->setVisible(false);
272                 tabs[visiblePane].pane->deactivateAllControls();
273                 visiblePane=i;
274                 tabs[visiblePane].button->setActive(true);
275                 tabs[visiblePane].pane->setVisible(true);
276                 tabs[visiblePane].pane->deactivateAllControls();
277                 buttonBarActive = true;
278                 draw();
279                 return true;
280             }
281         }
282     }
283     if (tabs[visiblePane].pane->mouseLBDOWN(x,y)) {
284         buttonBarActive = false;
285         tabs[visiblePane].button->dim();
286         symbolLeft.nextColour = Colour::BUTTONBACKGROUND;
287         symbolRight.nextColour = Colour::BUTTONBACKGROUND;
288         draw();
289         return true;
290     }
291     if (symbolLeft.mouseLBDOWN(x,y)) {
292         left();
293         draw();
294         return true;
295     }
296     if (symbolRight.mouseLBDOWN(x,y)) {
297         right();
298         draw();
299         return true;
300     }
301     return false;
302 }
303