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 28TabView::TabView() 29 : 30 fContainerView(NULL), 31 fLayoutItem(new TabLayoutItem(this)), 32 fLabel() 33{ 34} 35 36 37TabView::~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 45BSize 46TabView::MinSize() 47{ 48 BSize size(MaxSize()); 49 size.width = 60.0f; 50 return size; 51} 52 53 54BSize 55TabView::PreferredSize() 56{ 57 return MaxSize(); 58} 59 60 61BSize 62TabView::MaxSize() 63{ 64 float extra = be_control_look->DefaultLabelSpacing(); 65 float labelWidth = 300.0f; 66 return BSize(labelWidth, _LabelHeight() + extra); 67} 68 69 70void 71TabView::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 98void 99TabView::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 121void 122TabView::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 130void 131TabView::MouseDown(BPoint where, uint32 buttons) 132{ 133 fContainerView->SelectTab(this); 134} 135 136 137void 138TabView::MouseUp(BPoint where) 139{ 140} 141 142 143void 144TabView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage) 145{ 146} 147 148 149void 150TabView::Update() 151{ 152 fLayoutItem->InvalidateContainer(); 153} 154 155 156void 157TabView::SetContainerView(TabContainerView* containerView) 158{ 159 fContainerView = containerView; 160} 161 162 163TabContainerView* 164TabView::ContainerView() const 165{ 166 return fContainerView; 167} 168 169 170BLayoutItem* 171TabView::LayoutItem() const 172{ 173 return fLayoutItem; 174} 175 176 177void 178TabView::SetLabel(const char* label) 179{ 180 if (fLabel == label) 181 return; 182 183 fLabel = label; 184 fLayoutItem->InvalidateLayout(); 185} 186 187 188const BString& 189TabView::Label() const 190{ 191 return fLabel; 192} 193 194 195BRect 196TabView::Frame() const 197{ 198 return fLayoutItem->Frame(); 199} 200 201 202float 203TabView::_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 214TabLayoutItem::TabLayoutItem(TabView* parent) 215 : 216 fParent(parent), 217 fVisible(true) 218{ 219} 220 221 222bool 223TabLayoutItem::IsVisible() 224{ 225 return fVisible; 226} 227 228 229void 230TabLayoutItem::SetVisible(bool visible) 231{ 232 if (fVisible == visible) 233 return; 234 235 fVisible = visible; 236 237 InvalidateContainer(); 238 fParent->ContainerView()->InvalidateLayout(); 239} 240 241 242BRect 243TabLayoutItem::Frame() 244{ 245 return fFrame; 246} 247 248 249void 250TabLayoutItem::SetFrame(BRect frame) 251{ 252 BRect dirty = fFrame; 253 fFrame = frame; 254 dirty = dirty | fFrame; 255 InvalidateContainer(dirty); 256} 257 258 259BView* 260TabLayoutItem::View() 261{ 262 return NULL; 263} 264 265 266BSize 267TabLayoutItem::BaseMinSize() 268{ 269 return fParent->MinSize(); 270} 271 272 273BSize 274TabLayoutItem::BaseMaxSize() 275{ 276 return fParent->MaxSize(); 277} 278 279 280BSize 281TabLayoutItem::BasePreferredSize() 282{ 283 return fParent->PreferredSize(); 284} 285 286 287BAlignment 288TabLayoutItem::BaseAlignment() 289{ 290 return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 291} 292 293 294TabView* 295TabLayoutItem::Parent() const 296{ 297 return fParent; 298} 299 300 301void 302TabLayoutItem::InvalidateContainer() 303{ 304 InvalidateContainer(Frame()); 305} 306 307 308void 309TabLayoutItem::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