]> git.vomp.tv Git - vompclient-marten.git/blob - wtabbar.cc
Switch trunk code to new boxes
[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   }
50 }
51
52 void WTabBar::addTab(const char* name, Boxx* boxx)
53 {
54   TabDetails td;
55   td.name = name;
56   td.nameWidth = 0;
57   
58   for(UINT i = 0; i < strlen(name); i++)
59   {
60     td.nameWidth += charWidth(name[i]);
61   }
62
63   UINT newButtonX = 22;
64   for(UINT i = 0; i < tabs.size(); i++) newButtonX += tabs[i].button->getWidth() + 10;
65
66   WButton* newButton = new WButton();
67   newButton->setText(name);
68   newButton->setPosition(newButtonX, 2);
69   newButton->setSize(td.nameWidth + 6, Surface::getFontHeight());
70   if ((newButtonX + newButton->getWidth()) > (getWidth() - 22)) newButton->setVisible(false);
71   add(newButton);
72     
73   boxx->setPosition(0, 34);
74   boxx->setSize(getWidth(), getHeight()-34);
75   add(boxx);
76
77   td.button = newButton;
78   td.pane = boxx;
79   tabs.push_back(td);
80     
81   if (tabs.size() == 1)
82   {
83     newButton->setActive(true);
84     boxx->setVisible(true);
85   }
86   else
87   {
88     newButton->setActive(false);
89     boxx->setVisible(false);
90     symbolRight.nextColour = Colour::SELECTHIGHLIGHT;  // if this is the 2nd+ tab, ensure right arrow goes active
91   }
92 }
93
94 int WTabBar::handleCommand(int command)
95 {
96   // This returns 0 for not handled, and 1 for handled and please-update-me, 2 for handled-no-update
97
98   // if the focus is in a pane, send the command there
99   if (!buttonBarActive)
100   {
101     // Send the command to the pane
102     // Return code should be:
103       // 0 - not handled
104       // 1 - handled - stop command here
105       // 4 - handled - pane is returning control to here
106       // FIXME standardise these
107       
108     int paneRetCode = tabs[visiblePane].pane->handleCommand(command);
109     if (paneRetCode == 0)
110     {
111       return 0;
112     }
113     else if (paneRetCode == 1)
114     {
115       draw();
116       return 1;
117     }
118     else if (paneRetCode == 4)
119     {
120       buttonBarActive = true;
121       tabs[visiblePane].button->setActive(true);      
122       if (visiblePane != 0) symbolLeft.nextColour = Colour::SELECTHIGHLIGHT;
123       if (visiblePane != tabs.size() - 1) symbolRight.nextColour = Colour::SELECTHIGHLIGHT;
124       draw();
125       return 1;
126     }
127   }
128
129   if (buttonBarActive)
130   {
131     switch(command)
132     {
133       case Remote::DF_LEFT:
134       case Remote::LEFT:
135       {
136         if (!left()) return 2;
137         draw();
138         return 1;
139       }
140       case Remote::DF_RIGHT:
141       case Remote::RIGHT:
142       {
143         if (!right()) return 2;
144         draw();
145         return 1;
146       }
147       case Remote::DOWN:
148       case Remote::DF_DOWN:
149       {
150         buttonBarActive = false;
151         tabs[visiblePane].button->dim();
152         symbolLeft.nextColour = Colour::BUTTONBACKGROUND;
153         symbolRight.nextColour = Colour::BUTTONBACKGROUND;
154         if (tabs[visiblePane].pane->handleCommand(command) == 1) // shouldn't return anything else at this point?!
155         {
156           draw();
157           return 1;
158         }
159       }    
160     }  
161   }
162   return 0;  
163 }  
164
165 // When there are too many tabs to display simultaneously, extend this to shift the tabs left and right
166
167 bool WTabBar::left()
168 {
169   if (visiblePane == 0) return false;
170   tabs[visiblePane].button->setActive(false);
171   tabs[visiblePane].pane->setVisible(false);
172   --visiblePane;
173   tabs[visiblePane].button->setActive(true);
174   tabs[visiblePane].pane->setVisible(true);
175
176   if (visiblePane == 0) symbolLeft.nextColour = Colour::BUTTONBACKGROUND;
177   symbolRight.nextColour = Colour::SELECTHIGHLIGHT;
178
179   // Move the buttons..
180   if (tabs[visiblePane].button->getVisible() == false)
181   {
182     tabs[visiblePane].button->setVisible(true);
183     // We have gone << past the last visible button
184     UINT newButtonX = 22;
185     UINT j;
186     for(j = visiblePane; j < tabs.size(); j++) // start with the button just uncovered
187     {
188       if ((newButtonX + tabs[j].button->getWidth()) > (getWidth() - 22)) break; // this one too big.
189       tabs[j].button->setPosition(newButtonX, 2);
190       newButtonX += tabs[j].button->getWidth() + 10;
191     }
192     for(; j < tabs.size(); j++) // hide the rest
193     {
194       tabs[j].button->setVisible(false);
195     }
196   }
197
198   return true;
199 }
200
201 bool WTabBar::right()
202 {
203   if (visiblePane == tabs.size() - 1) return false;
204   tabs[visiblePane].button->setActive(false);
205   tabs[visiblePane].pane->setVisible(false);
206   ++visiblePane;
207   tabs[visiblePane].button->setActive(true);
208   tabs[visiblePane].pane->setVisible(true);
209   
210   if (visiblePane == tabs.size() - 1) symbolRight.nextColour = Colour::BUTTONBACKGROUND;
211   symbolLeft.nextColour = Colour::SELECTHIGHLIGHT;
212
213   // Move the buttons..
214   if (tabs[visiblePane].button->getVisible() == false)
215   {
216     tabs[visiblePane].button->setVisible(true);
217     // We have gone >> past the last visible button
218     // Move all buttons left, but need to work out which one to finally display as first on the left
219     UINT displayWidth = getWidth() - 44;
220     UINT widthSum = tabs[visiblePane].button->getWidth(); // start with width of newly shown button (on the right)
221     int startWith = 0;
222     int i;
223     for(i = visiblePane - 1; i >= 0; i--)
224     {
225       widthSum += tabs[i].button->getWidth() + 10; // add on width needed to display also the previous button
226       if (widthSum > displayWidth) // then it's too much
227       {
228         startWith = i + 1;
229         break;
230       }
231     }
232     
233     for(i = 0; i < startWith; i++) // For each button to the left of startWith...
234     {
235       tabs[i].button->setVisible(false);
236     }
237     
238     UINT newButtonX = 22;
239     for(UINT j = startWith; j <= visiblePane; j++) // startWith -> the one we just uncovered
240     {
241       tabs[j].button->setPosition(newButtonX, 2);
242       newButtonX += tabs[j].button->getWidth() + 10;
243     }      
244   }
245   
246   return true;
247 }
248