Use native BTabView with slight modifications.
* Add "left" and "right" tabs orientation. * Remove dependency on BControlLook which is private API.
This commit is contained in:
@@ -21,10 +21,11 @@
|
||||
//
|
||||
// File Name: YabTabView.cpp
|
||||
// Author: Marc Flerackers (mflerackers@androme.be)
|
||||
// Modified by Jan Bungeroth (jan@be-logos.org)
|
||||
// Modified by Jan Bungeroth (jan@be-logos.org)
|
||||
// Modified by Kacper Kasper (kacperkasper@gmail.com)
|
||||
// Description: YabTabView provides the framework for containing and
|
||||
// managing groups of BView objects. Modified for *sane*
|
||||
// view handling (they stay connected to the window).
|
||||
// view handling (they stay connected to the window).
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include <List.h>
|
||||
@@ -32,72 +33,24 @@
|
||||
#include <String.h>
|
||||
#include <View.h>
|
||||
#include <stdio.h>
|
||||
#include <ControlLook.h>
|
||||
#include "YabControlLook.h"
|
||||
#include "YabTabView.h"
|
||||
|
||||
#define X_OFFSET 0.0f
|
||||
|
||||
YabTabView::YabTabView(BRect frame, const char* name, button_width width, uint32 resizingMode, uint32 flags)
|
||||
: BView(frame, name, resizingMode, flags)
|
||||
: BTabView(frame, name, width, resizingMode, flags)
|
||||
{
|
||||
fTabList = new BList;
|
||||
fTabNames = new BList;
|
||||
|
||||
fTabWidthSetting = width;
|
||||
fSelection = 0;
|
||||
fFocus = -1;
|
||||
fTabOffset = 0.0f;
|
||||
|
||||
rgb_color color = ui_color(B_PANEL_BACKGROUND_COLOR);
|
||||
|
||||
SetViewColor(color);
|
||||
SetLowColor(color);
|
||||
|
||||
font_height fh;
|
||||
GetFontHeight(&fh);
|
||||
fTabHeight = fh.ascent + fh.descent + fh.leading + 8.0f;
|
||||
|
||||
/*
|
||||
if (layouted) {
|
||||
BGroupLayout* layout = new(std::nothrow) BGroupLayout(B_HORIZONTAL);
|
||||
if (layout) {
|
||||
layout->SetInsets(3.0, 3.0 + TabHeight() - 1, 3.0, 3.0);
|
||||
SetLayout(layout);
|
||||
}
|
||||
|
||||
fContainerView = new BView("view container", B_WILL_DRAW);
|
||||
fContainerView->SetLayout(new(std::nothrow) BCardLayout());
|
||||
} else {
|
||||
*/
|
||||
BRect bounds = Bounds();
|
||||
|
||||
bounds.top += TabHeight();
|
||||
bounds.InsetBy(3.0f, 3.0f);
|
||||
|
||||
fContainerView = new BView(bounds, "view container", B_FOLLOW_ALL,
|
||||
B_WILL_DRAW);
|
||||
// }
|
||||
|
||||
fContainerView->SetViewColor(color);
|
||||
fContainerView->SetLowColor(color);
|
||||
|
||||
AddChild(fContainerView);
|
||||
FocusChanged = 1;
|
||||
OldTabView = 1;
|
||||
|
||||
fTabOrientation = B_TAB_TOP;
|
||||
FocusChanged = 1;
|
||||
OldTabView = 1;
|
||||
}
|
||||
|
||||
YabTabView::~YabTabView()
|
||||
{
|
||||
for(int i=0; i<CountTabs(); i++)
|
||||
{
|
||||
delete TabAt(i);
|
||||
delete (BString*)fTabNames->RemoveItem(i);
|
||||
}
|
||||
|
||||
delete fTabList;
|
||||
delete fTabNames;
|
||||
}
|
||||
|
||||
@@ -105,129 +58,59 @@ void YabTabView::AddTab(BView *tabView, const char* label)
|
||||
{
|
||||
if(tabView)
|
||||
{
|
||||
tabView->Hide();
|
||||
fContainerView->AddChild(tabView);
|
||||
Invalidate();
|
||||
if(CountTabs() == 0) tabView->Show();
|
||||
BTab *tab = new BTab();
|
||||
BTabView::AddTab(tabView, tab);
|
||||
tab->SetLabel(label);
|
||||
// HACK
|
||||
// YAB assumes all views have a window, but that's not true for tabs
|
||||
if(CountTabs() > 1)
|
||||
AddChild(tabView);
|
||||
tabView->Hide();
|
||||
|
||||
|
||||
fTabList->AddItem(tabView);
|
||||
fTabNames->AddItem(new BString(label));
|
||||
}
|
||||
}
|
||||
|
||||
BView* YabTabView::RemoveTab(int32 index)
|
||||
{
|
||||
if(index < 0 || index >= CountTabs())
|
||||
return NULL;
|
||||
|
||||
BView *tab = (BView*)fTabList->RemoveItem(index);
|
||||
delete (BString*)fTabNames->RemoveItem(index);
|
||||
|
||||
if (index <= fSelection && fSelection != 0)
|
||||
fSelection--;
|
||||
|
||||
Select(fSelection);
|
||||
|
||||
if (fFocus == CountTabs() - 1)
|
||||
SetFocusTab(fFocus, false);
|
||||
else
|
||||
SetFocusTab(fFocus, true);
|
||||
|
||||
return tab;
|
||||
}
|
||||
|
||||
int32 YabTabView::CountTabs() const
|
||||
{
|
||||
return fTabList->CountItems();
|
||||
}
|
||||
|
||||
int32 YabTabView::Selection() const
|
||||
{
|
||||
return fSelection;
|
||||
}
|
||||
|
||||
void YabTabView::Select(int32 index)
|
||||
{
|
||||
if (index < 0 || index >= CountTabs())
|
||||
index = Selection();
|
||||
if (index < 0 || index >= CountTabs())
|
||||
index = Selection();
|
||||
|
||||
BView *tab = TabAt(Selection());
|
||||
if (tab)
|
||||
BTab* tab = TabAt(index);
|
||||
if (tab)
|
||||
{
|
||||
Invalidate();
|
||||
tab->Hide();
|
||||
FocusChanged = index+1;
|
||||
}
|
||||
|
||||
tab = TabAt(index);
|
||||
if (tab)
|
||||
{
|
||||
if (index != 0 && !Bounds().Contains(TabFrame(index))){
|
||||
if (!Bounds().Contains(TabFrame(index).LeftTop()))
|
||||
fTabOffset += TabFrame(index).left - Bounds().left - 20.0f;
|
||||
else
|
||||
fTabOffset += TabFrame(index).right - Bounds().right + 20.0f;
|
||||
}
|
||||
|
||||
|
||||
Invalidate();
|
||||
tab->Show();
|
||||
fSelection = index;
|
||||
FocusChanged = index+1;
|
||||
}
|
||||
// HACK
|
||||
// YAB assumes all views have a window, but that's not true for tabs
|
||||
int32 prevSelected = Selection();
|
||||
RemoveChild(tab->View());
|
||||
tab->View()->Show();
|
||||
BTabView::Select(index);
|
||||
if(prevSelected > -1) {
|
||||
BTab* prevTab = TabAt(prevSelected);
|
||||
prevTab->View()->Hide();
|
||||
AddChild(prevTab->View());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void YabTabView::MakeFocus(bool focused)
|
||||
{
|
||||
BView::MakeFocus(focused);
|
||||
BView::MakeFocus(focused);
|
||||
|
||||
SetFocusTab(Selection(), focused);
|
||||
}
|
||||
|
||||
int32 YabTabView::FocusTab() const
|
||||
{
|
||||
return fFocus;
|
||||
}
|
||||
SetFocusTab(Selection(), focused);
|
||||
}
|
||||
|
||||
void YabTabView::SetFocusTab(int32 tab, bool focused)
|
||||
{
|
||||
|
||||
if (tab >= CountTabs())
|
||||
tab = 0;
|
||||
|
||||
if (tab < 0)
|
||||
tab = CountTabs() - 1;
|
||||
|
||||
if (focused) {
|
||||
if (tab == fFocus)
|
||||
return;
|
||||
|
||||
if (fFocus != -1){
|
||||
if (TabAt (fFocus) != NULL)
|
||||
TabAt(fFocus)->MakeFocus(false);
|
||||
Invalidate(TabFrame(fFocus));
|
||||
}
|
||||
if (TabAt(tab) != NULL){
|
||||
TabAt(tab)->MakeFocus(true);
|
||||
Invalidate(TabFrame(tab));
|
||||
fFocus = tab;
|
||||
}
|
||||
} else if (fFocus != -1) {
|
||||
TabAt(fFocus)->MakeFocus(false);
|
||||
Invalidate(TabFrame(fFocus));
|
||||
fFocus = -1;
|
||||
}
|
||||
FocusChanged = (FocusTab() != tab) ? 1 : 0;
|
||||
|
||||
BTabView::SetFocusTab(tab, focused);
|
||||
}
|
||||
|
||||
BView* YabTabView::TabAt(int32 index)
|
||||
{
|
||||
if(index < 0 || index >= CountTabs())
|
||||
return NULL;
|
||||
|
||||
return (BView*)fTabList->ItemAt(index);
|
||||
}
|
||||
|
||||
const char* YabTabView::GetTabName(int32 index) const
|
||||
{
|
||||
if(index < 0 || index >= CountTabs())
|
||||
@@ -235,309 +118,3 @@ const char* YabTabView::GetTabName(int32 index) const
|
||||
|
||||
return ((BString*)fTabNames->ItemAt(index))->String();
|
||||
}
|
||||
|
||||
void YabTabView::KeyDown(const char *bytes, int32 numBytes)
|
||||
{
|
||||
if (IsHidden())
|
||||
return;
|
||||
|
||||
switch (bytes[0]) {
|
||||
case B_DOWN_ARROW:
|
||||
case B_LEFT_ARROW: {
|
||||
int32 focus = fFocus - 1;
|
||||
if (focus < 0)
|
||||
focus = CountTabs() - 1;
|
||||
SetFocusTab(focus, true);
|
||||
FocusChanged = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case B_UP_ARROW:
|
||||
case B_RIGHT_ARROW: {
|
||||
int32 focus = fFocus + 1;
|
||||
if (focus >= CountTabs())
|
||||
focus = 0;
|
||||
SetFocusTab(focus, true);
|
||||
FocusChanged = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case B_RETURN:
|
||||
case B_SPACE:
|
||||
Select(FocusTab());
|
||||
break;
|
||||
|
||||
default:
|
||||
BView::KeyDown(bytes, numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
void YabTabView::MouseDown(BPoint point)
|
||||
{
|
||||
if (fTabOrientation == B_TAB_TOP && point.y > fTabHeight)
|
||||
return;
|
||||
if (fTabOrientation == B_TAB_BOTTOM && point.y < Bounds().bottom-fTabHeight)
|
||||
return;
|
||||
|
||||
for (int32 i = 0; i < CountTabs(); i++) {
|
||||
if (TabFrame(i).Contains(point) && i != Selection()) {
|
||||
Select(i);
|
||||
fFocus = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BView::MouseDown(point);
|
||||
}
|
||||
|
||||
BRect YabTabView::TabFrame(int32 tab_index) const
|
||||
{
|
||||
float width = 100.0;
|
||||
float height = fTabHeight;;
|
||||
BRect tabFrame(Bounds());
|
||||
switch (fTabWidthSetting) {
|
||||
case B_WIDTH_FROM_LABEL:
|
||||
{
|
||||
float x = 0.0;
|
||||
for (int32 i = 0; i < tab_index; i++){
|
||||
x += StringWidth(GetTabName(i)) + 20.0;
|
||||
}
|
||||
|
||||
if(fTabOrientation == B_TAB_TOP)
|
||||
tabFrame.Set(x, 0.0, x + StringWidth(GetTabName(tab_index)) + 20.0, height);
|
||||
else
|
||||
tabFrame.Set(x, tabFrame.bottom - height, x + StringWidth(GetTabName(tab_index)) + 20.0, tabFrame.bottom);
|
||||
return tabFrame;
|
||||
}
|
||||
|
||||
case B_WIDTH_FROM_WIDEST:
|
||||
width = 0.0;
|
||||
for (int32 i = 0; i < CountTabs(); i++) {
|
||||
float tabWidth = StringWidth(GetTabName(i)) + 20.0;
|
||||
if (tabWidth > width)
|
||||
width = tabWidth;
|
||||
}
|
||||
// fall through
|
||||
|
||||
case B_WIDTH_AS_USUAL:
|
||||
default:
|
||||
if(fTabOrientation == B_TAB_TOP)
|
||||
tabFrame.Set(tab_index * width, 0.0, tab_index * width + width, height);
|
||||
else
|
||||
tabFrame.Set(tab_index * width, tabFrame.bottom - height, tab_index * width + width, tabFrame.bottom);
|
||||
return tabFrame;
|
||||
}
|
||||
}
|
||||
|
||||
void YabTabView::SetTabWidth(button_width width)
|
||||
{
|
||||
fTabWidthSetting = width;
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
button_width YabTabView::TabWidth() const
|
||||
{
|
||||
return fTabWidthSetting;
|
||||
}
|
||||
|
||||
void YabTabView::SetTabHeight(float height)
|
||||
{
|
||||
if (fTabHeight == height)
|
||||
return;
|
||||
|
||||
fContainerView->MoveBy(0.0f, height - fTabHeight);
|
||||
fContainerView->ResizeBy(0.0f, height - fTabHeight);
|
||||
|
||||
fTabHeight = height;
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
float YabTabView::TabHeight()
|
||||
{
|
||||
return fTabHeight;
|
||||
}
|
||||
|
||||
|
||||
BView *YabTabView::ContainerView()
|
||||
{
|
||||
return fContainerView;
|
||||
}
|
||||
|
||||
void YabTabView::Draw(BRect updateRect)
|
||||
{
|
||||
// DrawBox(DrawTabs());
|
||||
// SetHighColor(223,223,223);
|
||||
// StrokeLine(BPoint(Bounds().left, Bounds().bottom-TabHeight()-2), BPoint(Bounds().right, Bounds().bottom-TabHeight()-2));
|
||||
DrawBox(TabFrame(fSelection));
|
||||
DrawTabs();
|
||||
|
||||
if (IsFocus() && fFocus != -1)
|
||||
{
|
||||
DrawFocusMark(TabFrame(fFocus), fFocus);
|
||||
// Invalidate(TabFrame(fFocus));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BRect YabTabView::DrawTabs()
|
||||
{
|
||||
float left = 0;
|
||||
|
||||
for (int32 i = 0; i < CountTabs(); i++) {
|
||||
BRect tabFrame = TabFrame(i);
|
||||
DrawTab(tabFrame, i, i == fSelection ? B_TAB_FRONT : (i == 0) ? B_TAB_FIRST : B_TAB_ANY, i + 1 != fSelection);
|
||||
|
||||
left = tabFrame.right;
|
||||
}
|
||||
|
||||
BRect frame(Bounds());
|
||||
if (left < frame.right) {
|
||||
frame.left = left;
|
||||
if(fTabOrientation == B_TAB_TOP)
|
||||
frame.bottom = fTabHeight;
|
||||
else
|
||||
frame.top = frame.bottom - fTabHeight;
|
||||
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
|
||||
uint32 borders = BControlLook::B_TOP_BORDER
|
||||
| BControlLook::B_BOTTOM_BORDER | BControlLook::B_RIGHT_BORDER;
|
||||
if (left == 0)
|
||||
borders |= BControlLook::B_LEFT_BORDER;
|
||||
if(fTabOrientation == B_TAB_TOP)
|
||||
be_control_look->DrawInactiveTab(this, frame, frame, base, 0, borders);
|
||||
else
|
||||
fYabControlLook.DrawInactiveTabBottom(this, frame, frame, base, 0, borders);
|
||||
}
|
||||
|
||||
if (fSelection < CountTabs())
|
||||
return TabFrame(fSelection);
|
||||
|
||||
return BRect();
|
||||
}
|
||||
|
||||
void YabTabView::DrawLabel(int32 current, BRect frame)
|
||||
{
|
||||
BString label = GetTabName(current);
|
||||
if (label == NULL)
|
||||
return;
|
||||
|
||||
float frameWidth = frame.Width();
|
||||
float width = StringWidth(label.String());
|
||||
font_height fh;
|
||||
|
||||
if (width > frameWidth) {
|
||||
BFont font;
|
||||
GetFont(&font);
|
||||
font.TruncateString(&label, B_TRUNCATE_END, frameWidth);
|
||||
width = frameWidth;
|
||||
font.GetHeight(&fh);
|
||||
} else {
|
||||
GetFontHeight(&fh);
|
||||
}
|
||||
|
||||
SetDrawingMode(B_OP_OVER);
|
||||
SetHighColor(ui_color(B_CONTROL_TEXT_COLOR));
|
||||
DrawString(label.String(),
|
||||
BPoint((frame.left + frame.right - width) / 2.0,
|
||||
(frame.top + frame.bottom - fh.ascent - fh.descent) / 2.0
|
||||
+ fh.ascent));
|
||||
}
|
||||
|
||||
|
||||
void YabTabView::DrawTab(BRect frame, int32 current, tab_position position, bool full)
|
||||
{
|
||||
|
||||
BView *owner = this;
|
||||
rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR);
|
||||
|
||||
// uint32 borders = BControlLook::B_RIGHT_BORDER
|
||||
// | BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER;
|
||||
// if (frame.left == owner->Bounds().left)
|
||||
// borders |= BControlLook::B_LEFT_BORDER;
|
||||
// be_control_look->DrawButtonFrame(owner, frame, frame,
|
||||
// no_tint, 0, borders);
|
||||
// if (position == B_TAB_FRONT)
|
||||
// no_tint = tint_color(no_tint, B_DARKEN_2_TINT);
|
||||
// be_control_look->DrawButtonBackground(owner, frame, frame, no_tint);
|
||||
|
||||
uint32 borders = BControlLook::B_TOP_BORDER
|
||||
| BControlLook::B_BOTTOM_BORDER;
|
||||
if (frame.left == owner->Bounds().left)
|
||||
borders |= BControlLook::B_LEFT_BORDER;
|
||||
if (frame.right == owner->Bounds().right)
|
||||
borders |= BControlLook::B_RIGHT_BORDER;
|
||||
|
||||
if (position == B_TAB_FRONT) {
|
||||
if(fTabOrientation == B_TAB_TOP)
|
||||
{
|
||||
frame.bottom += 1;
|
||||
be_control_look->DrawActiveTab(owner, frame, frame, no_tint, 0, borders);
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.top -= 1;
|
||||
fYabControlLook.DrawActiveTabBottom(owner, frame, frame, no_tint, 0, borders);
|
||||
}
|
||||
} else {
|
||||
if(fTabOrientation == B_TAB_TOP)
|
||||
be_control_look->DrawInactiveTab(owner, frame, frame, no_tint, 0, borders);
|
||||
else
|
||||
fYabControlLook.DrawInactiveTabBottom(owner, frame, frame, no_tint, 0, borders);
|
||||
}
|
||||
|
||||
DrawLabel(current, frame);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void YabTabView::DrawFocusMark(BRect frame, int32 current)
|
||||
{
|
||||
float width = StringWidth(GetTabName(current));
|
||||
|
||||
SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
|
||||
|
||||
float offset = (fSelection == current) ? 3 : 2;
|
||||
StrokeLine(BPoint((frame.left + frame.right - width) / 2.0,
|
||||
frame.bottom - offset),
|
||||
BPoint((frame.left + frame.right + width) / 2.0,
|
||||
frame.bottom - offset));
|
||||
}
|
||||
|
||||
void YabTabView::DrawBox(BRect selTabRect)
|
||||
{
|
||||
BRect rect(Bounds());
|
||||
if(fTabOrientation == B_TAB_TOP)
|
||||
rect.top = selTabRect.bottom;
|
||||
else
|
||||
rect.bottom -= selTabRect.Height();
|
||||
|
||||
// BRegion clipping(Bounds());
|
||||
// selTabRect.left += 2;
|
||||
// selTabRect.right -= 2;
|
||||
// clipping.Exclude(selTabRect);
|
||||
// ConstrainClippingRegion(&clipping);
|
||||
|
||||
rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
|
||||
be_control_look->DrawGroupFrame(this, rect, rect, base);
|
||||
|
||||
// ConstrainClippingRegion(NULL);
|
||||
|
||||
}
|
||||
|
||||
void YabTabView::SetOrientation(tab_orientation side)
|
||||
{
|
||||
if(fTabOrientation != side)
|
||||
if(side == B_TAB_BOTTOM)
|
||||
fContainerView->MoveTo(3.0, 3.0);
|
||||
else
|
||||
fContainerView->MoveTo(3.0, TabHeight());
|
||||
fTabOrientation = side;
|
||||
}
|
||||
|
||||
tab_orientation YabTabView::Orientation()
|
||||
{
|
||||
return fTabOrientation;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user