1 /* 2 * Copyright (C) 2010 Rene Gollent <rene@gollent.com> 3 * Copyright (C) 2010 Stephan Aßmus <superstippi@gmx.de> 4 * 5 * All rights reserved. Distributed under the terms of the MIT License. 6 */ 7 8 #include "TabView.h" 9 10 #include <stdio.h> 11 12 #include <Application.h> 13 #include <Bitmap.h> 14 #include <Button.h> 15 #include <CardLayout.h> 16 #include <ControlLook.h> 17 #include <GroupView.h> 18 #include <SpaceLayoutItem.h> 19 #include <TabView.h> 20 #include <Window.h> 21 22 #include "TabContainerView.h" 23 24 25 // #pragma mark - TabView 26 27 28 TabView::TabView() 29 : 30 fContainerView(NULL), 31 fLayoutItem(new TabLayoutItem(this)), 32 fLabel() 33 { 34 } 35 36 37 TabView::~TabView() 38 { 39 // The layout item is deleted for us by the layout which contains it. 40 if (fContainerView == NULL) 41 delete fLayoutItem; 42 } 43 44 45 BSize 46 TabView::MinSize() 47 { 48 BSize size(MaxSize()); 49 size.width = 60.0f; 50 return size; 51 } 52 53 54 BSize 55 TabView::PreferredSize() 56 { 57 return MaxSize(); 58 } 59 60 61 BSize 62 TabView::MaxSize() 63 { 64 float extra = be_control_look->DefaultLabelSpacing(); 65 float labelWidth = 300.0f; 66 return BSize(labelWidth, _LabelHeight() + extra); 67 } 68 69 70 void 71 TabView::Draw(BRect updateRect) 72 { 73 BRect frame(fLayoutItem->Frame()); 74 frame.right++; 75 frame.bottom++; 76 77 int32 index = fContainerView->IndexOf(this); 78 79 // make room for tail of last tab 80 bool isLast = index == fContainerView->LastTabIndex(); 81 if (isLast) 82 frame.right -= 2; 83 84 DrawBackground(fContainerView, frame, updateRect); 85 86 bool isFront = index == fContainerView->SelectedTabIndex(); 87 if (isFront) 88 frame.top += 3.0f; 89 else 90 frame.top += 6.0f; 91 92 float spacing = be_control_look->DefaultLabelSpacing(); 93 frame.InsetBy(spacing, spacing / 2); 94 DrawContents(fContainerView, frame, updateRect); 95 } 96 97 98 void 99 TabView::DrawBackground(BView* owner, BRect frame, const BRect& updateRect) 100 { 101 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); 102 uint32 flags = 0; 103 uint32 borders = BControlLook::B_TOP_BORDER 104 | BControlLook::B_BOTTOM_BORDER; 105 106 int32 index = fContainerView->IndexOf(this); 107 int32 selected = fContainerView->SelectedTabIndex(); 108 int32 first = fContainerView->FirstTabIndex(); 109 int32 last = fContainerView->LastTabIndex(); 110 111 if (index == selected) { 112 be_control_look->DrawActiveTab(owner, frame, updateRect, base, flags, 113 borders, BControlLook::B_TOP_BORDER, index, selected, first, last); 114 } else { 115 be_control_look->DrawInactiveTab(owner, frame, updateRect, base, flags, 116 borders, BControlLook::B_TOP_BORDER, index, selected, first, last); 117 } 118 } 119 120 121 void 122 TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect) 123 { 124 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); 125 be_control_look->DrawLabel(owner, fLabel.String(), frame, updateRect, 126 base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE)); 127 } 128 129 130 void 131 TabView::MouseDown(BPoint where, uint32 buttons) 132 { 133 fContainerView->SelectTab(this); 134 } 135 136 137 void 138 TabView::MouseUp(BPoint where) 139 { 140 } 141 142 143 void 144 TabView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage) 145 { 146 } 147 148 149 void 150 TabView::Update() 151 { 152 fLayoutItem->InvalidateContainer(); 153 } 154 155 156 void 157 TabView::SetContainerView(TabContainerView* containerView) 158 { 159 fContainerView = containerView; 160 } 161 162 163 TabContainerView* 164 TabView::ContainerView() const 165 { 166 return fContainerView; 167 } 168 169 170 BLayoutItem* 171 TabView::LayoutItem() const 172 { 173 return fLayoutItem; 174 } 175 176 177 void 178 TabView::SetLabel(const char* label) 179 { 180 if (fLabel == label) 181 return; 182 183 fLabel = label; 184 fLayoutItem->InvalidateLayout(); 185 } 186 187 188 const BString& 189 TabView::Label() const 190 { 191 return fLabel; 192 } 193 194 195 BRect 196 TabView::Frame() const 197 { 198 return fLayoutItem->Frame(); 199 } 200 201 202 float 203 TabView::_LabelHeight() const 204 { 205 font_height fontHeight; 206 fContainerView->GetFontHeight(&fontHeight); 207 return ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); 208 } 209 210 211 // #pragma mark - TabLayoutItem 212 213 214 TabLayoutItem::TabLayoutItem(TabView* parent) 215 : 216 fParent(parent), 217 fVisible(true) 218 { 219 } 220 221 222 bool 223 TabLayoutItem::IsVisible() 224 { 225 return fVisible; 226 } 227 228 229 void 230 TabLayoutItem::SetVisible(bool visible) 231 { 232 if (fVisible == visible) 233 return; 234 235 fVisible = visible; 236 237 InvalidateContainer(); 238 fParent->ContainerView()->InvalidateLayout(); 239 } 240 241 242 BRect 243 TabLayoutItem::Frame() 244 { 245 return fFrame; 246 } 247 248 249 void 250 TabLayoutItem::SetFrame(BRect frame) 251 { 252 BRect dirty = fFrame; 253 fFrame = frame; 254 dirty = dirty | fFrame; 255 InvalidateContainer(dirty); 256 } 257 258 259 BView* 260 TabLayoutItem::View() 261 { 262 return NULL; 263 } 264 265 266 BSize 267 TabLayoutItem::BaseMinSize() 268 { 269 return fParent->MinSize(); 270 } 271 272 273 BSize 274 TabLayoutItem::BaseMaxSize() 275 { 276 return fParent->MaxSize(); 277 } 278 279 280 BSize 281 TabLayoutItem::BasePreferredSize() 282 { 283 return fParent->PreferredSize(); 284 } 285 286 287 BAlignment 288 TabLayoutItem::BaseAlignment() 289 { 290 return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 291 } 292 293 294 TabView* 295 TabLayoutItem::Parent() const 296 { 297 return fParent; 298 } 299 300 301 void 302 TabLayoutItem::InvalidateContainer() 303 { 304 InvalidateContainer(Frame()); 305 } 306 307 308 void 309 TabLayoutItem::InvalidateContainer(BRect frame) 310 { 311 // Invalidate more than necessary, to help the TabContainerView 312 // redraw the parts outside any tabs... need 2px 313 frame.bottom += 2; 314 frame.right += 2; 315 fParent->ContainerView()->Invalidate(frame); 316 } 317