Author: stippi Date: Thu Apr 15 12:19:16 2010 New Revision: 416 URL: http://mmlr.dyndns.org/changeset/416 Log: * Reworded defines in Jamfiles to make them more readable. * Split WebTabView into several files in a new sub-folder "tabview". * Implemented scrolling the tab view left/right when there are more tabs than fit into the view. * Fixed graphic glitches in the TabContainerView when the window is resized, the space behind the last tab was not managed properly. Added: webkit/trunk/WebKit/haiku/WebPositive/tabview/ webkit/trunk/WebKit/haiku/WebPositive/tabview/TabContainerView.cpp - copied, changed from r403, webkit/trunk/WebKit/haiku/WebPositive/WebTabView.cpp webkit/trunk/WebKit/haiku/WebPositive/tabview/TabContainerView.h - copied, changed from r403, webkit/trunk/WebKit/haiku/WebPositive/WebTabView.h webkit/trunk/WebKit/haiku/WebPositive/tabview/TabManager.cpp - copied, changed from r403, webkit/trunk/WebKit/haiku/WebPositive/WebTabView.cpp webkit/trunk/WebKit/haiku/WebPositive/tabview/TabManager.h - copied, changed from r403, webkit/trunk/WebKit/haiku/WebPositive/WebTabView.h webkit/trunk/WebKit/haiku/WebPositive/tabview/TabView.cpp - copied, changed from r403, webkit/trunk/WebKit/haiku/WebPositive/WebTabView.cpp webkit/trunk/WebKit/haiku/WebPositive/tabview/TabView.h - copied, changed from r403, webkit/trunk/WebKit/haiku/WebPositive/WebTabView.h Deleted: webkit/trunk/WebKit/haiku/WebPositive/WebTabView.cpp webkit/trunk/WebKit/haiku/WebPositive/WebTabView.h Modified: webkit/trunk/JavaScriptCore/Jamfile webkit/trunk/WebCore/Jamfile webkit/trunk/WebKit/Jamfile Modified: webkit/trunk/JavaScriptCore/Jamfile ============================================================================== --- webkit/trunk/JavaScriptCore/Jamfile Thu Apr 15 12:16:38 2010 (r415) +++ webkit/trunk/JavaScriptCore/Jamfile Thu Apr 15 12:19:16 2010 (r416) @@ -1,9 +1,18 @@ SubDir TOP JavaScriptCore ; -local defines = [ FDefines BUILDING_HAIKU__=1 ENABLE_YARR=1 - WTF_USE_PTHREADS=1 HAVE_POSIX_MEMALIGN=1 HAVE_SYS_TIME_H=1 ENABLE_DOM_STORAGE=1 - ENABLE_SVG=1 ENABLE_SVG_ANIMATION=1 ENABLE_SVG_FONTS=1 ENABLE_SVG_FOREIGN_OBJECT=1 - ENABLE_SVG_USE=1 ] ; +local defines = [ FDefines + BUILDING_HAIKU__=1 + ENABLE_YARR=1 + WTF_USE_PTHREADS=1 + HAVE_POSIX_MEMALIGN=1 + HAVE_SYS_TIME_H=1 + ENABLE_DOM_STORAGE=1 + ENABLE_SVG=1 + ENABLE_SVG_ANIMATION=1 + ENABLE_SVG_FONTS=1 + ENABLE_SVG_FOREIGN_OBJECT=1 + ENABLE_SVG_USE=1 +] ; # To turn off debugging symbols export NDEBUG=1 in the environment SubDirC++Flags $(defines) ; Modified: webkit/trunk/WebCore/Jamfile ============================================================================== --- webkit/trunk/WebCore/Jamfile Thu Apr 15 12:16:38 2010 (r415) +++ webkit/trunk/WebCore/Jamfile Thu Apr 15 12:19:16 2010 (r416) @@ -1,9 +1,18 @@ SubDir TOP WebCore ; -local defines = [ FDefines BUILDING_HAIKU__=1 ENABLE_YARR=1 - WTF_USE_PTHREADS=1 HAVE_POSIX_MEMALIGN=1 HAVE_SYS_TIME_H=1 ENABLE_DOM_STORAGE=1 - ENABLE_SVG=1 ENABLE_SVG_ANIMATION=1 ENABLE_SVG_FONTS=1 ENABLE_SVG_FOREIGN_OBJECT=1 - ENABLE_SVG_USE=1 ] ; +local defines = [ FDefines + BUILDING_HAIKU__=1 + ENABLE_YARR=1 + WTF_USE_PTHREADS=1 + HAVE_POSIX_MEMALIGN=1 + HAVE_SYS_TIME_H=1 + ENABLE_DOM_STORAGE=1 + ENABLE_SVG=1 + ENABLE_SVG_ANIMATION=1 + ENABLE_SVG_FONTS=1 + ENABLE_SVG_FOREIGN_OBJECT=1 + ENABLE_SVG_USE=1 +] ; # To turn off debugging symbols export NDEBUG=1 in the environment SubDirC++Flags $(defines) ; Modified: webkit/trunk/WebKit/Jamfile ============================================================================== --- webkit/trunk/WebKit/Jamfile Thu Apr 15 12:16:38 2010 (r415) +++ webkit/trunk/WebKit/Jamfile Thu Apr 15 12:19:16 2010 (r416) @@ -1,9 +1,18 @@ SubDir TOP WebKit ; -local defines = [ FDefines BUILDING_HAIKU__=1 ENABLE_YARR=1 - WTF_USE_PTHREADS=1 HAVE_POSIX_MEMALIGN=1 HAVE_SYS_TIME_H=1 ENABLE_DOM_STORAGE=1 - ENABLE_SVG=1 ENABLE_SVG_ANIMATION=1 ENABLE_SVG_FONTS=1 ENABLE_SVG_FOREIGN_OBJECT=1 - ENABLE_SVG_USE=1 ] ; +local defines = [ FDefines + BUILDING_HAIKU__=1 + ENABLE_YARR=1 + WTF_USE_PTHREADS=1 + HAVE_POSIX_MEMALIGN=1 + HAVE_SYS_TIME_H=1 + ENABLE_DOM_STORAGE=1 + ENABLE_SVG=1 + ENABLE_SVG_ANIMATION=1 + ENABLE_SVG_FONTS=1 + ENABLE_SVG_FOREIGN_OBJECT=1 + ENABLE_SVG_USE=1 +] ; # To turn off debugging symbols export NDEBUG=1 in the environment SubDirC++Flags $(defines) ; @@ -121,6 +130,7 @@ SEARCH_SOURCE += [ FDirName $(TOP) WebKit haiku WebPositive ] ; SEARCH_SOURCE += [ FDirName $(TOP) WebKit haiku WebPositive autocompletion ] ; SEARCH_SOURCE += [ FDirName $(TOP) WebKit haiku WebPositive support ] ; +SEARCH_SOURCE += [ FDirName $(TOP) WebKit haiku WebPositive tabview ] ; # SVN revision local svnRevisionFile = [ FGristFiles svn_revision ] ; @@ -140,6 +150,10 @@ IconButton.cpp SettingsMessage.cpp StringForSize.cpp + # tabview + TabContainerView.cpp + TabManager.cpp + TabView.cpp # WebPositive AuthenticationPanel.cpp BrowserApp.cpp @@ -151,7 +165,6 @@ SettingsWindow.cpp svn_revision.cpp URLInputGroup.cpp - WebTabView.cpp : libjavascriptcore.so libwebcore.so libwebkit.so Copied and modified: webkit/trunk/WebKit/haiku/WebPositive/tabview/TabContainerView.cpp (from r403, webkit/trunk/WebKit/haiku/WebPositive/WebTabView.cpp) ============================================================================== --- webkit/trunk/WebKit/haiku/WebPositive/WebTabView.cpp Thu Apr 8 15:52:28 2010 (r403, copy source) +++ webkit/trunk/WebKit/haiku/WebPositive/tabview/TabContainerView.cpp Thu Apr 15 12:19:16 2010 (r416) @@ -26,9 +26,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "WebTabView.h" +#include "TabContainerView.h" + +#include <stdio.h> -#include "WebView.h" #include <Application.h> #include <AbstractLayoutItem.h> #include <Bitmap.h> @@ -39,141 +40,8 @@ #include <MenuBar.h> #include <SpaceLayoutItem.h> #include <Window.h> -#include <stdio.h> - - -class TabView; -class TabContainerView; - - -class TabLayoutItem : public BAbstractLayoutItem { -public: - TabLayoutItem(TabView* parent); - - virtual bool IsVisible(); - virtual void SetVisible(bool visible); - - virtual BRect Frame(); - virtual void SetFrame(BRect frame); - - virtual BView* View(); - - virtual BSize BaseMinSize(); - virtual BSize BaseMaxSize(); - virtual BSize BasePreferredSize(); - virtual BAlignment BaseAlignment(); - - TabView* Parent() const; - -private: - TabView* fParent; - BRect fFrame; -}; - - -class TabView { -public: - TabView(); - virtual ~TabView(); - - virtual BSize MinSize(); - virtual BSize PreferredSize(); - virtual BSize MaxSize(); - - void Draw(BRect updateRect); - virtual void DrawBackground(BView* owner, BRect frame, - const BRect& updateRect, bool isFirst, bool isLast, bool isFront); - virtual void DrawContents(BView* owner, BRect frame, - const BRect& updateRect, bool isFirst, bool isLast, bool isFront); - - virtual void MouseDown(BPoint where, uint32 buttons); - virtual void MouseUp(BPoint where); - virtual void MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - - void SetIsFront(bool isFront); - bool IsFront() const; - void SetIsLast(bool isLast); - virtual void Update(bool isFirst, bool isLast, bool isFront); - - BLayoutItem* LayoutItem() const; - void SetContainerView(TabContainerView* containerView); - TabContainerView* ContainerView() const; - - void SetLabel(const char* label); - const BString& Label() const; - - BRect Frame() const; - -private: - float _LabelHeight() const; - -private: - TabContainerView* fContainerView; - TabLayoutItem* fLayoutItem; - - BString fLabel; - - bool fIsFirst; - bool fIsLast; - bool fIsFront; -}; - - -class TabContainerView : public BGroupView { -public: - class Controller { - public: - virtual void TabSelected(int32 tabIndex) = 0; - virtual bool HasFrames() = 0; - virtual TabView* CreateTabView() = 0; - virtual void DoubleClickOutsideTabs() = 0; - }; - -public: - TabContainerView(Controller* controller); - virtual ~TabContainerView(); - - virtual BSize MinSize(); - virtual void MessageReceived(BMessage*); - - virtual void Draw(BRect updateRect); - - virtual void MouseDown(BPoint where); - virtual void MouseUp(BPoint where); - virtual void MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - - virtual void DoLayout(); - - void AddTab(const char* label, int32 index = -1); - void AddTab(TabView* tab, int32 index = -1); - TabView* RemoveTab(int32 index); - TabView* TabAt(int32 index) const; - - int32 IndexOf(TabView* tab) const; - - void SelectTab(int32 tabIndex); - void SelectTab(TabView* tab); - - void SetTabLabel(int32 tabIndex, const char* label); - -private: - TabView* _TabAt(const BPoint& where) const; - void _MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - -private: - TabView* fLastMouseEventTab; - bool fMouseDown; - uint32 fClickCount; - TabView* fSelectedTab; - Controller* fController; -}; - - -// #pragma mark - TabContainerView +#include "TabView.h" static const float kLeftTabInset = 4; @@ -186,9 +54,10 @@ fMouseDown(false), fClickCount(0), fSelectedTab(NULL), - fController(controller) + fController(controller), + fFirstVisibleTabIndex(0) { - SetFlags(Flags() | B_WILL_DRAW); + SetFlags(Flags() | B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE); SetViewColor(B_TRANSPARENT_COLOR); GroupLayout()->SetInsets(kLeftTabInset, 0, 0, 1); GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue(), 0.0f); @@ -242,7 +111,7 @@ for (int32 i = 0; i < count; i++) { TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( layout->ItemAt(i)); - if (!item) + if (!item || !item->IsVisible()) continue; item->Parent()->Draw(updateRect); frame.left = item->Frame().right + 1; @@ -301,11 +170,8 @@ { BGroupView::DoLayout(); - BPoint where; - uint32 buttons; - GetMouse(&where, &buttons, false); - if (Bounds().Contains(where)) - _MouseMoved(where, B_INSIDE_VIEW, NULL); + _ValidateTabVisibility(); + _SendFakeMouseMoved(); } void @@ -345,6 +211,9 @@ if (item) item->Parent()->SetIsLast(false); } + + SetFirstVisibleTabIndex(MaxFirstVisibleTabIndex()); + _ValidateTabVisibility(); } TabView* @@ -394,6 +263,7 @@ } Invalidate(dirty); + _ValidateTabVisibility(); return removedTab; } @@ -466,967 +336,185 @@ } -TabView* -TabContainerView::_TabAt(const BPoint& where) const -{ - BGroupLayout* layout = GroupLayout(); - int32 count = layout->CountItems() - 1; - for (int32 i = 0; i < count; i++) { - TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( - layout->ItemAt(i)); - if (item && item->Frame().Contains(where)) - return item->Parent(); - } - return NULL; -} - - void -TabContainerView::_MouseMoved(BPoint where, uint32 _transit, - const BMessage* dragMessage) +TabContainerView::SetFirstVisibleTabIndex(int32 index) { - TabView* tab = _TabAt(where); - if (fMouseDown) { - uint32 transit = tab == fLastMouseEventTab - ? B_INSIDE_VIEW : B_OUTSIDE_VIEW; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, transit, dragMessage); + if (index < 0) + index = 0; + if (index > MaxFirstVisibleTabIndex()) + index = MaxFirstVisibleTabIndex(); + if (fFirstVisibleTabIndex == index) return; - } - - if (fLastMouseEventTab && fLastMouseEventTab == tab) - fLastMouseEventTab->MouseMoved(where, B_INSIDE_VIEW, dragMessage); - else { - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, B_EXITED_VIEW, dragMessage); - fLastMouseEventTab = tab; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage); - } -} + fFirstVisibleTabIndex = index; -// #pragma mark - TabView - - -TabView::TabView() - : fContainerView(NULL) - , fLayoutItem(new TabLayoutItem(this)) - , fLabel() -{ + _UpdateTabVisibility(); } -TabView::~TabView() -{ - // The layout item is deleted for us by the layout which contains it. - if (!fContainerView) - delete fLayoutItem; -} -BSize TabView::MinSize() -{ - BSize size(MaxSize()); - size.width = 100.0f; - return size; -} - -BSize TabView::PreferredSize() +int32 +TabContainerView::FirstVisibleTabIndex() const { - return MaxSize(); + return fFirstVisibleTabIndex; } -BSize TabView::MaxSize() -{ - float extra = be_control_look->DefaultLabelSpacing(); - float labelWidth = fContainerView->StringWidth(fLabel.String()) + 2 * extra; - labelWidth = min_c(300.0f, labelWidth); - return BSize(labelWidth, _LabelHeight() + extra); -} -void TabView::Draw(BRect updateRect) +int32 +TabContainerView::MaxFirstVisibleTabIndex() const { - BRect frame(fLayoutItem->Frame()); - if (fIsFront) { - // Extend the front tab outward left/right in order to merge - // the frames of adjacent tabs. - if (!fIsFirst) - frame.left--; - if (!fIsLast) - frame.right++; + float availableWidth = _AvailableWidthForTabs(); + if (availableWidth < 0) + return 0; + float visibleTabsWidth = 0; - frame.bottom++; - } - DrawBackground(fContainerView, frame, updateRect, fIsFirst, fIsLast, - fIsFront); - if (fIsFront) { - frame.top += 3.0f; - if (!fIsFirst) - frame.left++; - if (!fIsLast) - frame.right--; - } else - frame.top += 6.0f; - float spacing = be_control_look->DefaultLabelSpacing(); - frame.InsetBy(spacing, spacing / 2); - DrawContents(fContainerView, frame, updateRect, fIsFirst, fIsLast, - fIsFront); -} + BGroupLayout* layout = GroupLayout(); + int32 i = layout->CountItems() - 2; + for (; i >= 0; i--) { + TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( + layout->ItemAt(i)); + if (item == NULL) + continue; -void TabView::DrawBackground(BView* owner, BRect frame, const BRect& updateRect, - bool isFirst, bool isLast, bool isFront) -{ - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - uint32 borders = BControlLook::B_TOP_BORDER - | BControlLook::B_BOTTOM_BORDER; - if (isFirst) - borders |= BControlLook::B_LEFT_BORDER; - if (isLast) - borders |= BControlLook::B_RIGHT_BORDER; - if (isFront) { - be_control_look->DrawActiveTab(owner, frame, updateRect, base, - 0, borders); - } else { - be_control_look->DrawInactiveTab(owner, frame, updateRect, base, - 0, borders); + float itemWidth = item->MinSize().width; + if (availableWidth >= visibleTabsWidth + itemWidth) + visibleTabsWidth += itemWidth; + else { + // The tab before this tab is the last one that can be visible. + return i + 1; + } } -} - -void TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, - bool isFirst, bool isLast, bool isFront) -{ - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - be_control_look->DrawLabel(owner, fLabel.String(), frame, updateRect, - base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE)); -} -void TabView::MouseDown(BPoint where, uint32 buttons) -{ - fContainerView->SelectTab(this); + return 0; } -void TabView::MouseUp(BPoint where) -{ -} -void TabView::MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage) +bool +TabContainerView::CanScrollLeft() const { + return fFirstVisibleTabIndex < MaxFirstVisibleTabIndex(); } -void TabView::SetIsFront(bool isFront) -{ - Update(fIsFirst, fIsLast, isFront); -} -bool TabView::IsFront() const +bool +TabContainerView::CanScrollRight() const { - return fIsFront; -} - -void TabView::SetIsLast(bool isLast) -{ - Update(fIsFirst, isLast, fIsFront); -} - -void TabView::Update(bool isFirst, bool isLast, bool isFront) -{ - if (fIsFirst == isFirst && fIsLast == isLast && fIsFront == isFront) - return; - fIsFirst = isFirst; - fIsLast = isLast; - fIsFront = isFront; - BRect frame = fLayoutItem->Frame(); - frame.bottom++; - fContainerView->Invalidate(frame); -} - -void TabView::SetContainerView(TabContainerView* containerView) -{ - fContainerView = containerView; -} - -TabContainerView* TabView::ContainerView() const -{ - return fContainerView; -} - -BLayoutItem* TabView::LayoutItem() const -{ - return fLayoutItem; -} - -void TabView::SetLabel(const char* label) -{ - if (fLabel == label) - return; - fLabel = label; - fLayoutItem->InvalidateLayout(); -} - -const BString& TabView::Label() const -{ - return fLabel; -} - - -BRect -TabView::Frame() const -{ - return fLayoutItem->Frame(); -} - - -float TabView::_LabelHeight() const -{ - font_height fontHeight; - fContainerView->GetFontHeight(&fontHeight); - return ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); -} - -// #pragma mark - TabLayoutItem - -TabLayoutItem::TabLayoutItem(TabView* parent) - : fParent(parent) -{ -} - -bool TabLayoutItem::IsVisible() -{ - return !fParent->ContainerView()->IsHidden(fParent->ContainerView()); -} - -void TabLayoutItem::SetVisible(bool visible) -{ - // not allowed -} - -BRect TabLayoutItem::Frame() -{ - return fFrame; -} - -void TabLayoutItem::SetFrame(BRect frame) -{ - BRect dirty = fFrame; - fFrame = frame; - dirty = dirty | fFrame; - // Invalidate more than necessary, to help the TabContainerView - // redraw the parts outside any tabs... - dirty.bottom++; - dirty.right++; - fParent->ContainerView()->Invalidate(dirty); -} - -BView* TabLayoutItem::View() -{ - return NULL; -} - -BSize TabLayoutItem::BaseMinSize() -{ - return fParent->MinSize(); -} - -BSize TabLayoutItem::BaseMaxSize() -{ - return fParent->MaxSize(); -} - -BSize TabLayoutItem::BasePreferredSize() -{ - return fParent->PreferredSize(); -} - -BAlignment TabLayoutItem::BaseAlignment() -{ - return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); -} - -TabView* TabLayoutItem::Parent() const -{ - return fParent; -} - - -// #pragma mark - TabManagerController - - -class TabManagerController : public TabContainerView::Controller { -public: - TabManagerController(TabManager* manager); - - virtual ~TabManagerController(); - - virtual void TabSelected(int32 index) - { - fManager->SelectTab(index); - } - - virtual bool HasFrames() - { - return false; - } - - virtual TabView* CreateTabView(); - - virtual void DoubleClickOutsideTabs(); - - void CloseTab(int32 index); - - void SetCloseButtonsAvailable(bool available) - { - fCloseButtonsAvailable = available; - } - - bool CloseButtonsAvailable() const - { - return fCloseButtonsAvailable; + BGroupLayout* layout = GroupLayout(); + int32 count = layout->CountItems() - 1; + if (count > 0) { + TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( + layout->ItemAt(count - 1)); + return !item->IsVisible(); } - - void SetDoubleClickOutsideTabsMessage(const BMessage& message, - const BMessenger& target); - -private: - TabManager* fManager; - bool fCloseButtonsAvailable; - BMessage* fDoubleClickOutsideTabsMessage; - BMessenger fTarget; -}; - - -// #pragma mark - WebTabView - - -class WebTabView : public TabView { -public: - WebTabView(TabManagerController* controller); - ~WebTabView(); - - virtual BSize MaxSize(); - - virtual void DrawContents(BView* owner, BRect frame, const BRect& updateRect, - bool isFirst, bool isLast, bool isFront); - - virtual void MouseDown(BPoint where, uint32 buttons); - virtual void MouseUp(BPoint where); - virtual void MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - - void SetIcon(const BBitmap* icon); - -private: - void _DrawCloseButton(BView* owner, BRect& frame, const BRect& updateRect, - bool isFirst, bool isLast, bool isFront); - BRect _CloseRectFrame(BRect frame) const; - -private: - BBitmap* fIcon; - TabManagerController* fController; - bool fOverCloseRect; - bool fClicked; -}; - - -WebTabView::WebTabView(TabManagerController* controller) - : - TabView(), - fIcon(NULL), - fController(controller), - fOverCloseRect(false), - fClicked(false) -{ + return false; } -WebTabView::~WebTabView() -{ - delete fIcon; -} - - -static const int kIconSize = 18; -static const int kIconInset = 3; - - -BSize -WebTabView::MaxSize() -{ - // Account for icon. - BSize size(TabView::MaxSize()); - size.height = max_c(size.height, kIconSize + kIconInset * 2); - if (fIcon) - size.width += kIconSize + kIconInset * 2; - // Account for close button. - size.width += size.height; - return size; -} - - -void -WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, - bool isFirst, bool isLast, bool isFront) -{ - if (fController->CloseButtonsAvailable()) - _DrawCloseButton(owner, frame, updateRect, isFirst, isLast, isFront); - - if (fIcon) { - BRect iconBounds(0, 0, kIconSize - 1, kIconSize - 1); - // clip to icon bounds, if they are smaller - if (iconBounds.Contains(fIcon->Bounds())) - iconBounds = fIcon->Bounds(); - else { - // Try to scale down the icon by an even factor so the - // final size is between 14 and 18 pixel size. If this fails, - // the icon will simply be displayed at 18x18. - float scale = 2; - while ((fIcon->Bounds().Width() + 1) / scale > kIconSize) - scale *= 2; - if ((fIcon->Bounds().Width() + 1) / scale >= kIconSize - 4 - && (fIcon->Bounds().Height() + 1) / scale >= kIconSize - 4 - && (fIcon->Bounds().Height() + 1) / scale <= kIconSize) { - iconBounds.right = (fIcon->Bounds().Width() + 1) / scale - 1; - iconBounds.bottom = (fIcon->Bounds().Height() + 1) / scale - 1; - } - } - BPoint iconPos(frame.left + kIconInset - 1, - frame.top + floorf((frame.Height() - iconBounds.Height()) / 2)); - iconBounds.OffsetTo(iconPos); - owner->SetDrawingMode(B_OP_ALPHA); - owner->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); - owner->DrawBitmap(fIcon, fIcon->Bounds(), iconBounds, - B_FILTER_BITMAP_BILINEAR); - owner->SetDrawingMode(B_OP_COPY); - frame.left = frame.left + kIconSize + kIconInset * 2; - } - - TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, isFront); -} +// #pragma mark - -void -WebTabView::MouseDown(BPoint where, uint32 buttons) +TabView* +TabContainerView::_TabAt(const BPoint& where) const { - if (buttons & B_TERTIARY_MOUSE_BUTTON) { - fController->CloseTab(ContainerView()->IndexOf(this)); - return; - } - - BRect closeRect = _CloseRectFrame(Frame()); - if (!fController->CloseButtonsAvailable() || !closeRect.Contains(where)) { - TabView::MouseDown(where, buttons); - return; + BGroupLayout* layout = GroupLayout(); + int32 count = layout->CountItems() - 1; + for (int32 i = 0; i < count; i++) { + TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( + layout->ItemAt(i)); + if (item && item->IsVisible() && item->Frame().Contains(where)) + return item->Parent(); } - - fClicked = true; - ContainerView()->Invalidate(closeRect); + return NULL; } void -WebTabView::MouseUp(BPoint where) +TabContainerView::_MouseMoved(BPoint where, uint32 _transit, + const BMessage* dragMessage) { - if (!fClicked) { - TabView::MouseUp(where); + TabView* tab = _TabAt(where); + if (fMouseDown) { + uint32 transit = tab == fLastMouseEventTab + ? B_INSIDE_VIEW : B_OUTSIDE_VIEW; + if (fLastMouseEventTab) + fLastMouseEventTab->MouseMoved(where, transit, dragMessage); return; } - fClicked = false; - - if (_CloseRectFrame(Frame()).Contains(where)) - fController->CloseTab(ContainerView()->IndexOf(this)); -} - - -void -WebTabView::MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage) -{ - if (fController->CloseButtonsAvailable()) { - BRect closeRect = _CloseRectFrame(Frame()); - bool overCloseRect = closeRect.Contains(where); - if (overCloseRect != fOverCloseRect) { - fOverCloseRect = overCloseRect; - ContainerView()->Invalidate(closeRect); - } + if (fLastMouseEventTab && fLastMouseEventTab == tab) + fLastMouseEventTab->MouseMoved(where, B_INSIDE_VIEW, dragMessage); + else { + if (fLastMouseEventTab) + fLastMouseEventTab->MouseMoved(where, B_EXITED_VIEW, dragMessage); + fLastMouseEventTab = tab; + if (fLastMouseEventTab) + fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage); } - - TabView::MouseMoved(where, transit, dragMessage); } void -WebTabView::SetIcon(const BBitmap* icon) +TabContainerView::_ValidateTabVisibility() { - delete fIcon; - if (icon) - fIcon = new BBitmap(icon); + if (fFirstVisibleTabIndex > MaxFirstVisibleTabIndex()) + SetFirstVisibleTabIndex(MaxFirstVisibleTabIndex()); else - fIcon = NULL; - LayoutItem()->InvalidateLayout(); -} - - -BRect -WebTabView::_CloseRectFrame(BRect frame) const -{ - frame.left = frame.right - frame.Height(); - return frame; -} - - -void WebTabView::_DrawCloseButton(BView* owner, BRect& frame, - const BRect& updateRect, bool isFirst, bool isLast, bool isFront) -{ - BRect closeRect = _CloseRectFrame(frame); - frame.right = closeRect.left - be_control_look->DefaultLabelSpacing(); - - closeRect.left = (closeRect.left + closeRect.right) / 2 - 3; - closeRect.right = closeRect.left + 6; - closeRect.top = (closeRect.top + closeRect.bottom) / 2 - 3; - closeRect.bottom = closeRect.top + 6; - - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - float tint = B_DARKEN_1_TINT; - if (!IsFront()) { - base = tint_color(base, tint); - tint *= 1.02; - } - - if (fOverCloseRect) - tint *= 1.2; - - if (fClicked && fOverCloseRect) { - BRect buttonRect(closeRect.InsetByCopy(-4, -4)); - be_control_look->DrawButtonFrame(owner, buttonRect, updateRect, - base, base, - BControlLook::B_ACTIVATED | BControlLook::B_BLEND_FRAME); - be_control_look->DrawButtonBackground(owner, buttonRect, updateRect, - base, BControlLook::B_ACTIVATED); - tint *= 1.2; - closeRect.OffsetBy(1, 1); - } - - base = tint_color(base, tint); - owner->SetHighColor(base); - owner->SetPenSize(2); - owner->StrokeLine(closeRect.LeftTop(), closeRect.RightBottom()); - owner->StrokeLine(closeRect.LeftBottom(), closeRect.RightTop()); - owner->SetPenSize(1); -} - - -// #pragma mark - TabManagerController - - -TabManagerController::TabManagerController(TabManager* manager) - : - fManager(manager), - fCloseButtonsAvailable(false), - fDoubleClickOutsideTabsMessage(NULL) -{ -} - - -TabManagerController::~TabManagerController() -{ - delete fDoubleClickOutsideTabsMessage; -} - - -TabView* -TabManagerController::CreateTabView() -{ - return new WebTabView(this); -} - - -void -TabManagerController::DoubleClickOutsideTabs() -{ - fTarget.SendMessage(fDoubleClickOutsideTabsMessage); + _UpdateTabVisibility(); } void -TabManagerController::CloseTab(int32 index) +TabContainerView::_UpdateTabVisibility() { - fManager->CloseTab(index); -} - - -void -TabManagerController::SetDoubleClickOutsideTabsMessage(const BMessage& message, - const BMessenger& target) -{ - delete fDoubleClickOutsideTabsMessage; - fDoubleClickOutsideTabsMessage = new BMessage(message); - fTarget = target; -} - - -// #pragma mark - TabButtonContainer - - -class TabButtonContainer : public BGroupView { -public: - TabButtonContainer() - : BGroupView(B_HORIZONTAL) - { - SetFlags(Flags() | B_WILL_DRAW); - SetViewColor(B_TRANSPARENT_COLOR); - SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); - GroupLayout()->SetInsets(0, 6, 0, 0); - } - - virtual void Draw(BRect updateRect) - { - BRect bounds(Bounds()); - rgb_color base = LowColor(); - be_control_look->DrawInactiveTab(this, bounds, updateRect, - base, 0, BControlLook::B_TOP_BORDER); - } -}; - - -// #pragma mark - TabButton - - -class TabButton : public BButton { -public: - TabButton(BMessage* message) - : BButton("", message) - { - } - - virtual BSize MinSize() - { - return BSize(12, 12); - } - - virtual BSize MaxSize() - { - return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); - } - - virtual BSize PreferredSize() - { - return MinSize(); - } - - virtual void Draw(BRect updateRect) - { - BRect bounds(Bounds()); - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - SetHighColor(tint_color(base, B_DARKEN_2_TINT)); - StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); - bounds.bottom--; - uint32 flags = be_control_look->Flags(this); - uint32 borders = BControlLook::B_TOP_BORDER - | BControlLook::B_BOTTOM_BORDER; - be_control_look->DrawInactiveTab(this, bounds, updateRect, base, - flags, borders); - if (IsEnabled()) { - rgb_color button = tint_color(base, 1.07); - be_control_look->DrawButtonBackground(this, bounds, updateRect, - button, flags, 0); - } - - bounds.left = (bounds.left + bounds.right) / 2 - 6; - bounds.top = (bounds.top + bounds.bottom) / 2 - 6; - bounds.right = bounds.left + 12; - bounds.bottom = bounds.top + 12; - DrawSymbol(bounds, updateRect, base); - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - } -}; - - -class ScrollLeftTabButton : public TabButton { -public: - ScrollLeftTabButton(BMessage* message) - : TabButton(message) - { - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_LEFT_ARROW, 0, B_DARKEN_4_TINT); - } -}; - - -class ScrollRightTabButton : public TabButton { -public: - ScrollRightTabButton(BMessage* message) - : TabButton(message) - { - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_RIGHT_ARROW, 0, B_DARKEN_4_TINT); - } -}; - - -class NewTabButton : public TabButton { -public: - NewTabButton(BMessage* message) - : TabButton(message) - { - SetToolTip("New tab (Cmd-T)"); - } - - virtual BSize MinSize() - { - return BSize(18, 12); - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - SetHighColor(tint_color(base, B_DARKEN_4_TINT)); - float inset = 3; - frame.InsetBy(2, 2); - frame.top++; - frame.left++; - FillRoundRect(BRect(frame.left, frame.top + inset, - frame.right, frame.bottom - inset), 1, 1); - FillRoundRect(BRect(frame.left + inset, frame.top, - frame.right - inset, frame.bottom), 1, 1); - } -}; - - -class TabMenuTabButton : public TabButton { -public: - TabMenuTabButton(BMessage* message) - : TabButton(message) - { - } - - virtual BSize MinSize() - { - return BSize(18, 12); - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_DOWN_ARROW, 0, B_DARKEN_4_TINT); - } -}; - - -// #pragma mark - TabManager - - -TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) - : - fController(new TabManagerController(this)), - fTarget(target) -{ - fController->SetDoubleClickOutsideTabsMessage(*newTabMessage, - be_app_messenger); - - fContainerView = new BView("web view container", 0); - fCardLayout = new BCardLayout(); - fContainerView->SetLayout(fCardLayout); - - fTabContainerView = new TabContainerView(fController); - fTabContainerGroup = new BGroupView(B_HORIZONTAL); - fTabContainerGroup->GroupLayout()->SetInsets(0, 3, 0, 0); - -#if INTEGRATE_MENU_INTO_TAB_BAR - fMenu = new BMenu("Menu"); - BMenuBar* menuBar = new BMenuBar("Menu bar"); - menuBar->AddItem(fMenu); - TabButtonContainer* menuBarContainer = new TabButtonContainer(); - menuBarContainer->GroupLayout()->AddView(menuBar); - fTabContainerGroup->GroupLayout()->AddView(menuBarContainer, 0.0f); -#endif - - fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); -// fTabContainerGroup->GroupLayout()->AddView(new ScrollLeftTabButton(NULL), 0.0f); -// fTabContainerGroup->GroupLayout()->AddView(new ScrollRightTabButton(NULL), 0.0f); - NewTabButton* newTabButton = new NewTabButton(newTabMessage); - newTabButton->SetTarget(be_app); - fTabContainerGroup->GroupLayout()->AddView(newTabButton, 0.0f); -// fTabContainerGroup->GroupLayout()->AddView(new TabMenuTabButton(NULL), 0.0f); -} - - -TabManager::~TabManager() -{ - delete fController; -} - - -void -TabManager::SetTarget(const BMessenger& target) -{ - fTarget = target; -} - - -const BMessenger& -TabManager::Target() const -{ - return fTarget; -} - - -#if INTEGRATE_MENU_INTO_TAB_BAR -BMenu* -TabManager::Menu() const -{ - return fMenu; -} -#endif - - -BView* -TabManager::TabGroup() const -{ - return fTabContainerGroup; -} - - -BView* -TabManager::ContainerView() const -{ - return fContainerView; -} - - -BView* -TabManager::ViewForTab(int32 tabIndex) const -{ - BLayoutItem* item = fCardLayout->ItemAt(tabIndex); - if (item != NULL) - return item->View(); - return NULL; -} + float availableWidth = _AvailableWidthForTabs(); + if (availableWidth < 0) + return; + float visibleTabsWidth = 0; + bool canScrollTabsLeft = fFirstVisibleTabIndex > 0; + bool canScrollTabsRight = false; -int32 -TabManager::TabForView(const BView* containedView) const -{ - int32 count = fCardLayout->CountItems(); + BGroupLayout* layout = GroupLayout(); + int32 count = layout->CountItems() - 1; for (int32 i = 0; i < count; i++) { - BLayoutItem* item = fCardLayout->ItemAt(i); - if (item->View() == containedView) - return i; + TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( + layout->ItemAt(i)); + if (i < fFirstVisibleTabIndex) + item->SetVisible(false); + else { + float itemWidth = item->MinSize().width; + bool visible = availableWidth >= visibleTabsWidth + itemWidth; + item->SetVisible(visible && !canScrollTabsRight); + visibleTabsWidth += itemWidth; + if (!visible) + canScrollTabsRight = true; + } } - return -1; -} - - -void -TabManager::SelectTab(int32 tabIndex) -{ - fCardLayout->SetVisibleItem(tabIndex); - fTabContainerView->SelectTab(tabIndex); - - BMessage message(TAB_CHANGED); - message.AddInt32("tab index", tabIndex); - fTarget.SendMessage(&message); -} - - -void -TabManager::SelectTab(const BView* containedView) -{ - int32 tabIndex = TabForView(containedView); - if (tabIndex > 0) - SelectTab(tabIndex); -} - - -int32 -TabManager::SelectedTabIndex() const -{ - return fCardLayout->VisibleIndex(); -} - - -void -TabManager::CloseTab(int32 tabIndex) -{ - BMessage message(CLOSE_TAB); - message.AddInt32("tab index", tabIndex); - fTarget.SendMessage(&message); + fController->UpdateTabScrollability(canScrollTabsLeft, canScrollTabsRight); } -void -TabManager::AddTab(BView* view, const char* label, int32 index) -{ - fTabContainerView->AddTab(label, index); - fCardLayout->AddView(index, view); -} - - -BView* -TabManager::RemoveTab(int32 index) +float +TabContainerView::_AvailableWidthForTabs() const { - // It's important to remove the view first, since - // removing the tab will preliminary mess with the selected tab - // and then item count of card layout and tab container will not - // match yet. - BLayoutItem* item = fCardLayout->RemoveItem(index); - if (item == NULL) - return NULL; + float width = Bounds().Width() - 10; + // TODO: Don't really know why -10 is needed above. - TabView* tab = fTabContainerView->RemoveTab(index); - delete tab; + float left; + float right; + GroupLayout()->GetInsets(&left, NULL, &right, NULL); + width -= left + right; - BView* view = item->View(); - delete item; - return view; -} - - -int32 -TabManager::CountTabs() const -{ - return fCardLayout->CountItems(); + return width; } void -TabManager::SetTabLabel(int32 tabIndex, const char* label) +TabContainerView::_SendFakeMouseMoved() { - fTabContainerView->SetTabLabel(tabIndex, label); -} - - -void -TabManager::SetTabIcon(const BView* containedView, const BBitmap* icon) -{ - WebTabView* tab = dynamic_cast<WebTabView*>(fTabContainerView->TabAt( - TabForView(containedView))); - if (tab) - tab->SetIcon(icon); -} - - -void -TabManager::SetCloseButtonsAvailable(bool available) -{ - if (available == fController->CloseButtonsAvailable()) - return; - fController->SetCloseButtonsAvailable(available); - fTabContainerView->Invalidate(); + BPoint where; + uint32 buttons; + GetMouse(&where, &buttons, false); + if (Bounds().Contains(where)) + _MouseMoved(where, B_INSIDE_VIEW, NULL); } - Copied and modified: webkit/trunk/WebKit/haiku/WebPositive/tabview/TabContainerView.h (from r403, webkit/trunk/WebKit/haiku/WebPositive/WebTabView.h) ============================================================================== --- webkit/trunk/WebKit/haiku/WebPositive/WebTabView.h Thu Apr 8 15:52:28 2010 (r403, copy source) +++ webkit/trunk/WebKit/haiku/WebPositive/tabview/TabContainerView.h Thu Apr 15 12:19:16 2010 (r416) @@ -24,70 +24,79 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifndef TAB_CONTAINER_VIEW_H +#define TAB_CONTAINER_VIEW_H -#ifndef TAB_MANAGER_H -#define TAB_MANAGER_H +#include <GroupView.h> -#include <Messenger.h> -#include <TabView.h> -enum { - TAB_CHANGED = 'tcha', - CLOSE_TAB = 'cltb' -}; +class TabView; + -class BBitmap; -class BCardLayout; -class BGroupView; -class BMenu; -class TabContainerView; -class TabManagerController; +class TabContainerView : public BGroupView { +public: + class Controller { + public: + virtual void TabSelected(int32 tabIndex) = 0; + virtual bool HasFrames() = 0; + virtual TabView* CreateTabView() = 0; + virtual void DoubleClickOutsideTabs() = 0; + virtual void UpdateTabScrollability(bool canScrollLeft, + bool canScrollRight) = 0; + }; -class TabManager { public: - TabManager(const BMessenger& target, - BMessage* newTabMessage); - virtual ~TabManager(); - - void SetTarget(const BMessenger& target); - const BMessenger& Target() const; - -#if INTEGRATE_MENU_INTO_TAB_BAR - BMenu* Menu() const; -#endif + TabContainerView(Controller* controller); + virtual ~TabContainerView(); + + virtual BSize MinSize(); + + virtual void MessageReceived(BMessage*); + + virtual void Draw(BRect updateRect); - BView* TabGroup() const; - BView* ContainerView() const; + virtual void MouseDown(BPoint where); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); - BView* ViewForTab(int32 tabIndex) const; - int32 TabForView(const BView* containedView) const; + virtual void DoLayout(); + + void AddTab(const char* label, int32 index = -1); + void AddTab(TabView* tab, int32 index = -1); + TabView* RemoveTab(int32 index); + TabView* TabAt(int32 index) const; + + int32 IndexOf(TabView* tab) const; void SelectTab(int32 tabIndex); - void SelectTab(const BView* containedView); - int32 SelectedTabIndex() const; - void CloseTab(int32 tabIndex); - - void AddTab(BView* view, const char* label, - int32 index = -1); - BView* RemoveTab(int32 index); - int32 CountTabs() const; + void SelectTab(TabView* tab); void SetTabLabel(int32 tabIndex, const char* label); - void SetTabIcon(const BView* containedView, - const BBitmap* icon); - void SetCloseButtonsAvailable(bool available); + + void SetFirstVisibleTabIndex(int32 index); + int32 FirstVisibleTabIndex() const; + int32 MaxFirstVisibleTabIndex() const; + + bool CanScrollLeft() const; + bool CanScrollRight() const; private: -#if INTEGRATE_MENU_INTO_TAB_BAR - BMenu* fMenu; -#endif - BGroupView* fTabContainerGroup; - TabContainerView* fTabContainerView; - BView* fContainerView; - BCardLayout* fCardLayout; - TabManagerController* fController; + TabView* _TabAt(const BPoint& where) const; + void _MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); + void _ValidateTabVisibility(); + void _UpdateTabVisibility(); + float _AvailableWidthForTabs() const; + void _SendFakeMouseMoved(); - BMessenger fTarget; +private: + TabView* fLastMouseEventTab; + bool fMouseDown; + uint32 fClickCount; + TabView* fSelectedTab; + Controller* fController; + int32 fFirstVisibleTabIndex; }; -#endif // TAB_MANAGER_H +#endif // TAB_CONTAINER_VIEW_H Copied and modified: webkit/trunk/WebKit/haiku/WebPositive/tabview/TabManager.cpp (from r403, webkit/trunk/WebKit/haiku/WebPositive/WebTabView.cpp) ============================================================================== --- webkit/trunk/WebKit/haiku/WebPositive/WebTabView.cpp Thu Apr 8 15:52:28 2010 (r403, copy source) +++ webkit/trunk/WebKit/haiku/WebPositive/tabview/TabManager.cpp Thu Apr 15 12:19:16 2010 (r416) @@ -26,9 +26,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "WebTabView.h" +#include "TabManager.h" + +#include <stdio.h> -#include "WebView.h" #include <Application.h> #include <AbstractLayoutItem.h> #include <Bitmap.h> @@ -39,716 +40,245 @@ #include <MenuBar.h> #include <SpaceLayoutItem.h> #include <Window.h> -#include <stdio.h> - - -class TabView; -class TabContainerView; - - -class TabLayoutItem : public BAbstractLayoutItem { -public: - TabLayoutItem(TabView* parent); - - virtual bool IsVisible(); - virtual void SetVisible(bool visible); - - virtual BRect Frame(); - virtual void SetFrame(BRect frame); - - virtual BView* View(); - - virtual BSize BaseMinSize(); - virtual BSize BaseMaxSize(); - virtual BSize BasePreferredSize(); - virtual BAlignment BaseAlignment(); - - TabView* Parent() const; - -private: - TabView* fParent; - BRect fFrame; -}; - - -class TabView { -public: - TabView(); - virtual ~TabView(); - - virtual BSize MinSize(); - virtual BSize PreferredSize(); - virtual BSize MaxSize(); - - void Draw(BRect updateRect); - virtual void DrawBackground(BView* owner, BRect frame, - const BRect& updateRect, bool isFirst, bool isLast, bool isFront); - virtual void DrawContents(BView* owner, BRect frame, - const BRect& updateRect, bool isFirst, bool isLast, bool isFront); - - virtual void MouseDown(BPoint where, uint32 buttons); - virtual void MouseUp(BPoint where); - virtual void MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - - void SetIsFront(bool isFront); - bool IsFront() const; - void SetIsLast(bool isLast); - virtual void Update(bool isFirst, bool isLast, bool isFront); - - BLayoutItem* LayoutItem() const; - void SetContainerView(TabContainerView* containerView); - TabContainerView* ContainerView() const; - - void SetLabel(const char* label); - const BString& Label() const; - - BRect Frame() const; -private: - float _LabelHeight() const; - -private: - TabContainerView* fContainerView; - TabLayoutItem* fLayoutItem; +#include "TabContainerView.h" +#include "TabView.h" - BString fLabel; - - bool fIsFirst; - bool fIsLast; - bool fIsFront; -}; +// #pragma mark - Helper classes -class TabContainerView : public BGroupView { -public: - class Controller { - public: - virtual void TabSelected(int32 tabIndex) = 0; - virtual bool HasFrames() = 0; - virtual TabView* CreateTabView() = 0; - virtual void DoubleClickOutsideTabs() = 0; - }; +class TabButton : public BButton { public: - TabContainerView(Controller* controller); - virtual ~TabContainerView(); - - virtual BSize MinSize(); - - virtual void MessageReceived(BMessage*); - - virtual void Draw(BRect updateRect); - - virtual void MouseDown(BPoint where); - virtual void MouseUp(BPoint where); - virtual void MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - - virtual void DoLayout(); - - void AddTab(const char* label, int32 index = -1); - void AddTab(TabView* tab, int32 index = -1); - TabView* RemoveTab(int32 index); - TabView* TabAt(int32 index) const; - - int32 IndexOf(TabView* tab) const; - - void SelectTab(int32 tabIndex); - void SelectTab(TabView* tab); - - void SetTabLabel(int32 tabIndex, const char* label); - -private: - TabView* _TabAt(const BPoint& where) const; - void _MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - -private: - TabView* fLastMouseEventTab; - bool fMouseDown; - uint32 fClickCount; - TabView* fSelectedTab; - Controller* fController; -}; - - -// #pragma mark - TabContainerView - - -static const float kLeftTabInset = 4; - - -TabContainerView::TabContainerView(Controller* controller) - : - BGroupView(B_HORIZONTAL), - fLastMouseEventTab(NULL), - fMouseDown(false), - fClickCount(0), - fSelectedTab(NULL), - fController(controller) -{ - SetFlags(Flags() | B_WILL_DRAW); - SetViewColor(B_TRANSPARENT_COLOR); - GroupLayout()->SetInsets(kLeftTabInset, 0, 0, 1); - GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue(), 0.0f); -} - - -TabContainerView::~TabContainerView() -{ -} - - -BSize -TabContainerView::MinSize() -{ - // Eventually, we want to be scrolling if the tabs don't fit. - BSize size(BGroupView::MinSize()); - size.width = 300; - return size; -} - - -void -TabContainerView::MessageReceived(BMessage* message) -{ - switch (message->what) { - default: - BGroupView::MessageReceived(message); + TabButton(BMessage* message) + : BButton("", message) + { } -} - -void -TabContainerView::Draw(BRect updateRect) -{ - // Stroke separator line at bottom. - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - BRect frame(Bounds()); - SetHighColor(tint_color(base, B_DARKEN_2_TINT)); - StrokeLine(frame.LeftBottom(), frame.RightBottom()); - frame.bottom--; - - // Draw empty area before first tab. - uint32 borders = BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER; - BRect leftFrame(frame.left, frame.top, kLeftTabInset, frame.bottom); - be_control_look->DrawInactiveTab(this, leftFrame, updateRect, base, 0, - borders); - - // Draw all tabs, keeping track of where they end. - BGroupLayout* layout = GroupLayout(); - int32 count = layout->CountItems() - 1; - for (int32 i = 0; i < count; i++) { - TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( - layout->ItemAt(i)); - if (!item) - continue; - item->Parent()->Draw(updateRect); - frame.left = item->Frame().right + 1; + virtual BSize MinSize() + { + return BSize(12, 12); } - // Draw empty area after last tab. - be_control_look->DrawInactiveTab(this, frame, updateRect, base, 0, borders); -} - - -void -TabContainerView::MouseDown(BPoint where) -{ - uint32 buttons; - if (Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons) != B_OK) - buttons = B_PRIMARY_MOUSE_BUTTON; - uint32 clicks; - if (Window()->CurrentMessage()->FindInt32("clicks", (int32*)&clicks) != B_OK) - clicks = 1; - fMouseDown = true; - SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); - if (fLastMouseEventTab) - fLastMouseEventTab->MouseDown(where, buttons); - else { - if (clicks > 1) - fClickCount++; - else - fClickCount = 1; + virtual BSize MaxSize() + { + return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); } -} - -void -TabContainerView::MouseUp(BPoint where) -{ - fMouseDown = false; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseUp(where); - else if (fClickCount > 1) { - fClickCount = 0; - fController->DoubleClickOutsideTabs(); + virtual BSize PreferredSize() + { + return MinSize(); } -} - - -void -TabContainerView::MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage) -{ - _MouseMoved(where, transit, dragMessage); -} - - -void -TabContainerView::DoLayout() -{ - BGroupView::DoLayout(); - - BPoint where; - uint32 buttons; - GetMouse(&where, &buttons, false); - if (Bounds().Contains(where)) - _MouseMoved(where, B_INSIDE_VIEW, NULL); -} -void -TabContainerView::AddTab(const char* label, int32 index) -{ - TabView* tab; - if (fController) - tab = fController->CreateTabView(); - else - tab = new TabView(); - tab->SetLabel(label); - AddTab(tab, index); -} - - -void -TabContainerView::AddTab(TabView* tab, int32 index) -{ - tab->SetContainerView(this); - - if (index == -1) - index = GroupLayout()->CountItems() - 1; + virtual void Draw(BRect updateRect) + { + BRect bounds(Bounds()); + rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); + SetHighColor(tint_color(base, B_DARKEN_2_TINT)); + StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); + bounds.bottom--; + uint32 flags = be_control_look->Flags(this); + uint32 borders = BControlLook::B_TOP_BORDER + | BControlLook::B_BOTTOM_BORDER; + be_control_look->DrawInactiveTab(this, bounds, updateRect, base, + 0, borders); + if (IsEnabled()) { + rgb_color button = tint_color(base, 1.07); + be_control_look->DrawButtonBackground(this, bounds, updateRect, + button, flags, 0); + } - bool hasFrames = fController != NULL && fController->HasFrames(); - bool isFirst = index == 0 && hasFrames; - bool isLast = index == GroupLayout()->CountItems() - 1 && hasFrames; - bool isFront = fSelectedTab == NULL; - tab->Update(isFirst, isLast, isFront); - - GroupLayout()->AddItem(index, tab->LayoutItem()); - - if (isFront) - SelectTab(tab); - if (isLast) { - TabLayoutItem* item - = dynamic_cast<TabLayoutItem*>(GroupLayout()->ItemAt(index - 1)); - if (item) - item->Parent()->SetIsLast(false); + bounds.left = (bounds.left + bounds.right) / 2 - 6; + bounds.top = (bounds.top + bounds.bottom) / 2 - 6; + bounds.right = bounds.left + 12; + bounds.bottom = bounds.top + 12; + DrawSymbol(bounds, updateRect, base); } -} - -TabView* -TabContainerView::RemoveTab(int32 index) -{ - TabLayoutItem* item - = dynamic_cast<TabLayoutItem*>(GroupLayout()->RemoveItem(index)); - if (!item) - return NULL; - - BRect dirty(Bounds()); - dirty.left = item->Frame().left; - TabView* removedTab = item->Parent(); - removedTab->SetContainerView(NULL); - - if (removedTab == fLastMouseEventTab) - fLastMouseEventTab = NULL; - - // Update tabs after or before the removed tab. - bool hasFrames = fController != NULL && fController->HasFrames(); - item = dynamic_cast<TabLayoutItem*>(GroupLayout()->ItemAt(index)); - if (item) { - // This tab is behind the removed tab. - TabView* tab = item->Parent(); - tab->Update(index == 0 && hasFrames, - index == GroupLayout()->CountItems() - 2 && hasFrames, - tab == fSelectedTab); - if (removedTab == fSelectedTab) { - fSelectedTab = NULL; - SelectTab(tab); - } else if (fController && tab == fSelectedTab) - fController->TabSelected(index); - } else { - // The removed tab was the last tab. - item = dynamic_cast<TabLayoutItem*>(GroupLayout()->ItemAt(index - 1)); - if (item) { - TabView* tab = item->Parent(); - tab->Update(index == 0 && hasFrames, - index == GroupLayout()->CountItems() - 2 && hasFrames, - tab == fSelectedTab); - if (removedTab == fSelectedTab) { - fSelectedTab = NULL; - SelectTab(tab); - } - } + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { } +}; - Invalidate(dirty); - - return removedTab; -} - - -TabView* -TabContainerView::TabAt(int32 index) const -{ - TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( - GroupLayout()->ItemAt(index)); - if (item) - return item->Parent(); - return NULL; -} - - -int32 -TabContainerView::IndexOf(TabView* tab) const -{ - return GroupLayout()->IndexOfItem(tab->LayoutItem()); -} - - -void -TabContainerView::SelectTab(int32 index) -{ - TabView* tab = NULL; - TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( - GroupLayout()->ItemAt(index)); - if (item) - tab = item->Parent(); - - SelectTab(tab); -} - - -void -TabContainerView::SelectTab(TabView* tab) -{ - if (tab == fSelectedTab) - return; - - if (fSelectedTab) - fSelectedTab->SetIsFront(false); - - fSelectedTab = tab; - - if (fSelectedTab) - fSelectedTab->SetIsFront(true); - - if (fController != NULL) { - int32 index = -1; - if (fSelectedTab != NULL) - index = GroupLayout()->IndexOfItem(tab->LayoutItem()); - fController->TabSelected(index); +class ScrollLeftTabButton : public TabButton { +public: + ScrollLeftTabButton(BMessage* message) + : TabButton(message) + { } -} - -void -TabContainerView::SetTabLabel(int32 tabIndex, const char* label) -{ - TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( - GroupLayout()->ItemAt(tabIndex)); - if (item == NULL) - return; - - item->Parent()->SetLabel(label); -} - - -TabView* -TabContainerView::_TabAt(const BPoint& where) const -{ - BGroupLayout* layout = GroupLayout(); - int32 count = layout->CountItems() - 1; - for (int32 i = 0; i < count; i++) { - TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( - layout->ItemAt(i)); - if (item && item->Frame().Contains(where)) - return item->Parent(); + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + float tint = IsEnabled() ? B_DARKEN_4_TINT : B_DARKEN_1_TINT; + be_control_look->DrawArrowShape(this, frame, updateRect, + base, BControlLook::B_LEFT_ARROW, 0, tint); } - return NULL; -} +}; -void -TabContainerView::_MouseMoved(BPoint where, uint32 _transit, - const BMessage* dragMessage) -{ - TabView* tab = _TabAt(where); - if (fMouseDown) { - uint32 transit = tab == fLastMouseEventTab - ? B_INSIDE_VIEW : B_OUTSIDE_VIEW; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, transit, dragMessage); - return; +class ScrollRightTabButton : public TabButton { +public: + ScrollRightTabButton(BMessage* message) + : TabButton(message) + { } - if (fLastMouseEventTab && fLastMouseEventTab == tab) - fLastMouseEventTab->MouseMoved(where, B_INSIDE_VIEW, dragMessage); - else { - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, B_EXITED_VIEW, dragMessage); - fLastMouseEventTab = tab; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage); + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + frame.OffsetBy(1, 0); + float tint = IsEnabled() ? B_DARKEN_4_TINT : B_DARKEN_1_TINT; + be_control_look->DrawArrowShape(this, frame, updateRect, + base, BControlLook::B_RIGHT_ARROW, 0, tint); } -} - - -// #pragma mark - TabView - - -TabView::TabView() - : fContainerView(NULL) - , fLayoutItem(new TabLayoutItem(this)) - , fLabel() -{ -} - -TabView::~TabView() -{ - // The layout item is deleted for us by the layout which contains it. - if (!fContainerView) - delete fLayoutItem; -} - -BSize TabView::MinSize() -{ - BSize size(MaxSize()); - size.width = 100.0f; - return size; -} - -BSize TabView::PreferredSize() -{ - return MaxSize(); -} - -BSize TabView::MaxSize() -{ - float extra = be_control_look->DefaultLabelSpacing(); - float labelWidth = fContainerView->StringWidth(fLabel.String()) + 2 * extra; - labelWidth = min_c(300.0f, labelWidth); - return BSize(labelWidth, _LabelHeight() + extra); -} +}; -void TabView::Draw(BRect updateRect) -{ - BRect frame(fLayoutItem->Frame()); - if (fIsFront) { - // Extend the front tab outward left/right in order to merge - // the frames of adjacent tabs. - if (!fIsFirst) - frame.left--; - if (!fIsLast) - frame.right++; - frame.bottom++; +class NewTabButton : public TabButton { +public: + NewTabButton(BMessage* message) + : TabButton(message) + { + SetToolTip("New tab (Cmd-T)"); } - DrawBackground(fContainerView, frame, updateRect, fIsFirst, fIsLast, - fIsFront); - if (fIsFront) { - frame.top += 3.0f; - if (!fIsFirst) - frame.left++; - if (!fIsLast) - frame.right--; - } else - frame.top += 6.0f; - float spacing = be_control_look->DefaultLabelSpacing(); - frame.InsetBy(spacing, spacing / 2); - DrawContents(fContainerView, frame, updateRect, fIsFirst, fIsLast, - fIsFront); -} -void TabView::DrawBackground(BView* owner, BRect frame, const BRect& updateRect, - bool isFirst, bool isLast, bool isFront) -{ - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - uint32 borders = BControlLook::B_TOP_BORDER - | BControlLook::B_BOTTOM_BORDER; - if (isFirst) - borders |= BControlLook::B_LEFT_BORDER; - if (isLast) - borders |= BControlLook::B_RIGHT_BORDER; - if (isFront) { - be_control_look->DrawActiveTab(owner, frame, updateRect, base, - 0, borders); - } else { - be_control_look->DrawInactiveTab(owner, frame, updateRect, base, - 0, borders); + virtual BSize MinSize() + { + return BSize(18, 12); } -} - -void TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, - bool isFirst, bool isLast, bool isFront) -{ - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - be_control_look->DrawLabel(owner, fLabel.String(), frame, updateRect, - base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE)); -} - -void TabView::MouseDown(BPoint where, uint32 buttons) -{ - fContainerView->SelectTab(this); -} - -void TabView::MouseUp(BPoint where) -{ -} - -void TabView::MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage) -{ -} - -void TabView::SetIsFront(bool isFront) -{ - Update(fIsFirst, fIsLast, isFront); -} - -bool TabView::IsFront() const -{ - return fIsFront; -} - -void TabView::SetIsLast(bool isLast) -{ - Update(fIsFirst, isLast, fIsFront); -} - -void TabView::Update(bool isFirst, bool isLast, bool isFront) -{ - if (fIsFirst == isFirst && fIsLast == isLast && fIsFront == isFront) - return; - fIsFirst = isFirst; - fIsLast = isLast; - fIsFront = isFront; - BRect frame = fLayoutItem->Frame(); - frame.bottom++; - fContainerView->Invalidate(frame); -} - -void TabView::SetContainerView(TabContainerView* containerView) -{ - fContainerView = containerView; -} - -TabContainerView* TabView::ContainerView() const -{ - return fContainerView; -} - -BLayoutItem* TabView::LayoutItem() const -{ - return fLayoutItem; -} - -void TabView::SetLabel(const char* label) -{ - if (fLabel == label) - return; - fLabel = label; - fLayoutItem->InvalidateLayout(); -} - -const BString& TabView::Label() const -{ - return fLabel; -} + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + SetHighColor(tint_color(base, B_DARKEN_4_TINT)); + float inset = 3; + frame.InsetBy(2, 2); + frame.top++; + frame.left++; + FillRoundRect(BRect(frame.left, frame.top + inset, + frame.right, frame.bottom - inset), 1, 1); + FillRoundRect(BRect(frame.left + inset, frame.top, + frame.right - inset, frame.bottom), 1, 1); + } +}; -BRect -TabView::Frame() const -{ - return fLayoutItem->Frame(); -} +class TabMenuTabButton : public TabButton { +public: + TabMenuTabButton(BMessage* message) + : TabButton(message) + { + } -float TabView::_LabelHeight() const -{ - font_height fontHeight; - fContainerView->GetFontHeight(&fontHeight); - return ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); -} + virtual BSize MinSize() + { + return BSize(18, 12); + } -// #pragma mark - TabLayoutItem + virtual void DrawSymbol(BRect frame, const BRect& updateRect, + const rgb_color& base) + { + be_control_look->DrawArrowShape(this, frame, updateRect, + base, BControlLook::B_DOWN_ARROW, 0, B_DARKEN_4_TINT); + } +}; -TabLayoutItem::TabLayoutItem(TabView* parent) - : fParent(parent) -{ -} -bool TabLayoutItem::IsVisible() -{ - return !fParent->ContainerView()->IsHidden(fParent->ContainerView()); -} +enum { + MSG_SCROLL_TABS_LEFT = 'stlt', + MSG_SCROLL_TABS_RIGHT = 'strt' +}; -void TabLayoutItem::SetVisible(bool visible) -{ - // not allowed -} -BRect TabLayoutItem::Frame() -{ - return fFrame; -} +class TabContainerGroup : public BGroupView { +public: + TabContainerGroup(TabContainerView* tabContainerView) + : + BGroupView(B_HORIZONTAL), + fTabContainerView(tabContainerView), + fScrollLeftTabButton(NULL), + fScrollRightTabButton(NULL) + { + } -void TabLayoutItem::SetFrame(BRect frame) -{ - BRect dirty = fFrame; - fFrame = frame; - dirty = dirty | fFrame; - // Invalidate more than necessary, to help the TabContainerView - // redraw the parts outside any tabs... - dirty.bottom++; - dirty.right++; - fParent->ContainerView()->Invalidate(dirty); -} + virtual void AttachedToWindow() + { + if (fScrollLeftTabButton != NULL) + fScrollLeftTabButton->SetTarget(this); + if (fScrollRightTabButton != NULL) + fScrollRightTabButton->SetTarget(this); + } -BView* TabLayoutItem::View() -{ - return NULL; -} + virtual void MessageReceived(BMessage* message) + { + switch (message->what) { + case MSG_SCROLL_TABS_LEFT: + fTabContainerView->SetFirstVisibleTabIndex( + fTabContainerView->FirstVisibleTabIndex() - 1); + break; + case MSG_SCROLL_TABS_RIGHT: + fTabContainerView->SetFirstVisibleTabIndex( + fTabContainerView->FirstVisibleTabIndex() + 1); + break; + default: + BGroupView::MessageReceived(message); + break; + } + } -BSize TabLayoutItem::BaseMinSize() -{ - return fParent->MinSize(); -} + void AddScrollLeftButton(TabButton* button) + { + fScrollLeftTabButton = button; + GroupLayout()->AddView(button, 0.0f); + } -BSize TabLayoutItem::BaseMaxSize() -{ - return fParent->MaxSize(); -} + void AddScrollRightButton(TabButton* button) + { + fScrollRightTabButton = button; + GroupLayout()->AddView(button, 0.0f); + } -BSize TabLayoutItem::BasePreferredSize() -{ - return fParent->PreferredSize(); -} + void EnableScrollButtons(bool canScrollLeft, bool canScrollRight) + { + fScrollLeftTabButton->SetEnabled(canScrollLeft); + fScrollRightTabButton->SetEnabled(canScrollRight); + if (!canScrollLeft && !canScrollRight) { + // hide scroll buttons + } else { + // show scroll buttons + } + } -BAlignment TabLayoutItem::BaseAlignment() -{ - return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); -} +private: + TabContainerView* fTabContainerView; + TabButton* fScrollLeftTabButton; + TabButton* fScrollRightTabButton; +}; -TabView* TabLayoutItem::Parent() const -{ - return fParent; -} +class TabButtonContainer : public BGroupView { +public: + TabButtonContainer() + : + BGroupView(B_HORIZONTAL) + { + SetFlags(Flags() | B_WILL_DRAW); + SetViewColor(B_TRANSPARENT_COLOR); + SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + GroupLayout()->SetInsets(0, 6, 0, 0); + } -// #pragma mark - TabManagerController + virtual void Draw(BRect updateRect) + { + BRect bounds(Bounds()); + rgb_color base = LowColor(); + be_control_look->DrawInactiveTab(this, bounds, updateRect, + base, 0, BControlLook::B_TOP_BORDER); + } +}; class TabManagerController : public TabContainerView::Controller { @@ -771,6 +301,12 @@ virtual void DoubleClickOutsideTabs(); + virtual void UpdateTabScrollability(bool canScrollLeft, + bool canScrollRight) + { + fTabContainerGroup->EnableScrollButtons(canScrollLeft, canScrollRight); + } + void CloseTab(int32 index); void SetCloseButtonsAvailable(bool available) @@ -786,11 +322,17 @@ void SetDoubleClickOutsideTabsMessage(const BMessage& message, const BMessenger& target); + void SetTabContainerGroup(TabContainerGroup* tabContainerGroup) + { + fTabContainerGroup = tabContainerGroup; + } + private: - TabManager* fManager; - bool fCloseButtonsAvailable; - BMessage* fDoubleClickOutsideTabsMessage; - BMessenger fTarget; + TabManager* fManager; + TabContainerGroup* fTabContainerGroup; + bool fCloseButtonsAvailable; + BMessage* fDoubleClickOutsideTabsMessage; + BMessenger fTarget; }; @@ -1021,6 +563,7 @@ TabManagerController::TabManagerController(TabManager* manager) : fManager(manager), + fTabContainerGroup(NULL), fCloseButtonsAvailable(false), fDoubleClickOutsideTabsMessage(NULL) { @@ -1064,169 +607,6 @@ } -// #pragma mark - TabButtonContainer - - -class TabButtonContainer : public BGroupView { -public: - TabButtonContainer() - : BGroupView(B_HORIZONTAL) - { - SetFlags(Flags() | B_WILL_DRAW); - SetViewColor(B_TRANSPARENT_COLOR); - SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); - GroupLayout()->SetInsets(0, 6, 0, 0); - } - - virtual void Draw(BRect updateRect) - { - BRect bounds(Bounds()); - rgb_color base = LowColor(); - be_control_look->DrawInactiveTab(this, bounds, updateRect, - base, 0, BControlLook::B_TOP_BORDER); - } -}; - - -// #pragma mark - TabButton - - -class TabButton : public BButton { -public: - TabButton(BMessage* message) - : BButton("", message) - { - } - - virtual BSize MinSize() - { - return BSize(12, 12); - } - - virtual BSize MaxSize() - { - return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); - } - - virtual BSize PreferredSize() - { - return MinSize(); - } - - virtual void Draw(BRect updateRect) - { - BRect bounds(Bounds()); - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - SetHighColor(tint_color(base, B_DARKEN_2_TINT)); - StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); - bounds.bottom--; - uint32 flags = be_control_look->Flags(this); - uint32 borders = BControlLook::B_TOP_BORDER - | BControlLook::B_BOTTOM_BORDER; - be_control_look->DrawInactiveTab(this, bounds, updateRect, base, - flags, borders); - if (IsEnabled()) { - rgb_color button = tint_color(base, 1.07); - be_control_look->DrawButtonBackground(this, bounds, updateRect, - button, flags, 0); - } - - bounds.left = (bounds.left + bounds.right) / 2 - 6; - bounds.top = (bounds.top + bounds.bottom) / 2 - 6; - bounds.right = bounds.left + 12; - bounds.bottom = bounds.top + 12; - DrawSymbol(bounds, updateRect, base); - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - } -}; - - -class ScrollLeftTabButton : public TabButton { -public: - ScrollLeftTabButton(BMessage* message) - : TabButton(message) - { - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_LEFT_ARROW, 0, B_DARKEN_4_TINT); - } -}; - - -class ScrollRightTabButton : public TabButton { -public: - ScrollRightTabButton(BMessage* message) - : TabButton(message) - { - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_RIGHT_ARROW, 0, B_DARKEN_4_TINT); - } -}; - - -class NewTabButton : public TabButton { -public: - NewTabButton(BMessage* message) - : TabButton(message) - { - SetToolTip("New tab (Cmd-T)"); - } - - virtual BSize MinSize() - { - return BSize(18, 12); - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - SetHighColor(tint_color(base, B_DARKEN_4_TINT)); - float inset = 3; - frame.InsetBy(2, 2); - frame.top++; - frame.left++; - FillRoundRect(BRect(frame.left, frame.top + inset, - frame.right, frame.bottom - inset), 1, 1); - FillRoundRect(BRect(frame.left + inset, frame.top, - frame.right - inset, frame.bottom), 1, 1); - } -}; - - -class TabMenuTabButton : public TabButton { -public: - TabMenuTabButton(BMessage* message) - : TabButton(message) - { - } - - virtual BSize MinSize() - { - return BSize(18, 12); - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_DOWN_ARROW, 0, B_DARKEN_4_TINT); - } -}; - - // #pragma mark - TabManager @@ -1243,9 +623,11 @@ fContainerView->SetLayout(fCardLayout); fTabContainerView = new TabContainerView(fController); - fTabContainerGroup = new BGroupView(B_HORIZONTAL); + fTabContainerGroup = new TabContainerGroup(fTabContainerView); fTabContainerGroup->GroupLayout()->SetInsets(0, 3, 0, 0); + fController->SetTabContainerGroup(fTabContainerGroup); + #if INTEGRATE_MENU_INTO_TAB_BAR fMenu = new BMenu("Menu"); BMenuBar* menuBar = new BMenuBar("Menu bar"); @@ -1256,8 +638,10 @@ #endif fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); -// fTabContainerGroup->GroupLayout()->AddView(new ScrollLeftTabButton(NULL), 0.0f); -// fTabContainerGroup->GroupLayout()->AddView(new ScrollRightTabButton(NULL), 0.0f); + fTabContainerGroup->AddScrollLeftButton(new ScrollLeftTabButton( + new BMessage(MSG_SCROLL_TABS_LEFT))); + fTabContainerGroup->AddScrollRightButton(new ScrollRightTabButton( + new BMessage(MSG_SCROLL_TABS_RIGHT))); NewTabButton* newTabButton = new NewTabButton(newTabMessage); newTabButton->SetTarget(be_app); fTabContainerGroup->GroupLayout()->AddView(newTabButton, 0.0f); Copied and modified: webkit/trunk/WebKit/haiku/WebPositive/tabview/TabManager.h (from r403, webkit/trunk/WebKit/haiku/WebPositive/WebTabView.h) ============================================================================== --- webkit/trunk/WebKit/haiku/WebPositive/WebTabView.h Thu Apr 8 15:52:28 2010 (r403, copy source) +++ webkit/trunk/WebKit/haiku/WebPositive/tabview/TabManager.h Thu Apr 15 12:19:16 2010 (r416) @@ -40,6 +40,7 @@ class BCardLayout; class BGroupView; class BMenu; +class TabContainerGroup; class TabContainerView; class TabManagerController; @@ -81,7 +82,7 @@ #if INTEGRATE_MENU_INTO_TAB_BAR BMenu* fMenu; #endif - BGroupView* fTabContainerGroup; + TabContainerGroup* fTabContainerGroup; TabContainerView* fTabContainerView; BView* fContainerView; BCardLayout* fCardLayout; Copied and modified: webkit/trunk/WebKit/haiku/WebPositive/tabview/TabView.cpp (from r403, webkit/trunk/WebKit/haiku/WebPositive/WebTabView.cpp) ============================================================================== --- webkit/trunk/WebKit/haiku/WebPositive/WebTabView.cpp Thu Apr 8 15:52:28 2010 (r403, copy source) +++ webkit/trunk/WebKit/haiku/WebPositive/tabview/TabView.cpp Thu Apr 15 12:19:16 2010 (r416) @@ -26,11 +26,11 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "WebTabView.h" +#include "TabView.h" + +#include <stdio.h> -#include "WebView.h" #include <Application.h> -#include <AbstractLayoutItem.h> #include <Bitmap.h> #include <Button.h> #include <CardLayout.h> @@ -39,483 +39,22 @@ #include <MenuBar.h> #include <SpaceLayoutItem.h> #include <Window.h> -#include <stdio.h> - - -class TabView; -class TabContainerView; - - -class TabLayoutItem : public BAbstractLayoutItem { -public: - TabLayoutItem(TabView* parent); - - virtual bool IsVisible(); - virtual void SetVisible(bool visible); - - virtual BRect Frame(); - virtual void SetFrame(BRect frame); - - virtual BView* View(); - - virtual BSize BaseMinSize(); - virtual BSize BaseMaxSize(); - virtual BSize BasePreferredSize(); - virtual BAlignment BaseAlignment(); - - TabView* Parent() const; - -private: - TabView* fParent; - BRect fFrame; -}; - - -class TabView { -public: - TabView(); - virtual ~TabView(); - - virtual BSize MinSize(); - virtual BSize PreferredSize(); - virtual BSize MaxSize(); - - void Draw(BRect updateRect); - virtual void DrawBackground(BView* owner, BRect frame, - const BRect& updateRect, bool isFirst, bool isLast, bool isFront); - virtual void DrawContents(BView* owner, BRect frame, - const BRect& updateRect, bool isFirst, bool isLast, bool isFront); - - virtual void MouseDown(BPoint where, uint32 buttons); - virtual void MouseUp(BPoint where); - virtual void MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - - void SetIsFront(bool isFront); - bool IsFront() const; - void SetIsLast(bool isLast); - virtual void Update(bool isFirst, bool isLast, bool isFront); - - BLayoutItem* LayoutItem() const; - void SetContainerView(TabContainerView* containerView); - TabContainerView* ContainerView() const; - - void SetLabel(const char* label); - const BString& Label() const; - - BRect Frame() const; - -private: - float _LabelHeight() const; - -private: - TabContainerView* fContainerView; - TabLayoutItem* fLayoutItem; - - BString fLabel; - - bool fIsFirst; - bool fIsLast; - bool fIsFront; -}; - - -class TabContainerView : public BGroupView { -public: - class Controller { - public: - virtual void TabSelected(int32 tabIndex) = 0; - virtual bool HasFrames() = 0; - virtual TabView* CreateTabView() = 0; - virtual void DoubleClickOutsideTabs() = 0; - }; - -public: - TabContainerView(Controller* controller); - virtual ~TabContainerView(); - - virtual BSize MinSize(); - - virtual void MessageReceived(BMessage*); - - virtual void Draw(BRect updateRect); - - virtual void MouseDown(BPoint where); - virtual void MouseUp(BPoint where); - virtual void MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - - virtual void DoLayout(); - - void AddTab(const char* label, int32 index = -1); - void AddTab(TabView* tab, int32 index = -1); - TabView* RemoveTab(int32 index); - TabView* TabAt(int32 index) const; - - int32 IndexOf(TabView* tab) const; - - void SelectTab(int32 tabIndex); - void SelectTab(TabView* tab); - - void SetTabLabel(int32 tabIndex, const char* label); - -private: - TabView* _TabAt(const BPoint& where) const; - void _MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - -private: - TabView* fLastMouseEventTab; - bool fMouseDown; - uint32 fClickCount; - TabView* fSelectedTab; - Controller* fController; -}; - - -// #pragma mark - TabContainerView - - -static const float kLeftTabInset = 4; - - -TabContainerView::TabContainerView(Controller* controller) - : - BGroupView(B_HORIZONTAL), - fLastMouseEventTab(NULL), - fMouseDown(false), - fClickCount(0), - fSelectedTab(NULL), - fController(controller) -{ - SetFlags(Flags() | B_WILL_DRAW); - SetViewColor(B_TRANSPARENT_COLOR); - GroupLayout()->SetInsets(kLeftTabInset, 0, 0, 1); - GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue(), 0.0f); -} - - -TabContainerView::~TabContainerView() -{ -} - - -BSize -TabContainerView::MinSize() -{ - // Eventually, we want to be scrolling if the tabs don't fit. - BSize size(BGroupView::MinSize()); - size.width = 300; - return size; -} - - -void -TabContainerView::MessageReceived(BMessage* message) -{ - switch (message->what) { - default: - BGroupView::MessageReceived(message); - } -} - - -void -TabContainerView::Draw(BRect updateRect) -{ - // Stroke separator line at bottom. - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - BRect frame(Bounds()); - SetHighColor(tint_color(base, B_DARKEN_2_TINT)); - StrokeLine(frame.LeftBottom(), frame.RightBottom()); - frame.bottom--; - - // Draw empty area before first tab. - uint32 borders = BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER; - BRect leftFrame(frame.left, frame.top, kLeftTabInset, frame.bottom); - be_control_look->DrawInactiveTab(this, leftFrame, updateRect, base, 0, - borders); - - // Draw all tabs, keeping track of where they end. - BGroupLayout* layout = GroupLayout(); - int32 count = layout->CountItems() - 1; - for (int32 i = 0; i < count; i++) { - TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( - layout->ItemAt(i)); - if (!item) - continue; - item->Parent()->Draw(updateRect); - frame.left = item->Frame().right + 1; - } - - // Draw empty area after last tab. - be_control_look->DrawInactiveTab(this, frame, updateRect, base, 0, borders); -} - - -void -TabContainerView::MouseDown(BPoint where) -{ - uint32 buttons; - if (Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons) != B_OK) - buttons = B_PRIMARY_MOUSE_BUTTON; - uint32 clicks; - if (Window()->CurrentMessage()->FindInt32("clicks", (int32*)&clicks) != B_OK) - clicks = 1; - fMouseDown = true; - SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); - if (fLastMouseEventTab) - fLastMouseEventTab->MouseDown(where, buttons); - else { - if (clicks > 1) - fClickCount++; - else - fClickCount = 1; - } -} - - -void -TabContainerView::MouseUp(BPoint where) -{ - fMouseDown = false; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseUp(where); - else if (fClickCount > 1) { - fClickCount = 0; - fController->DoubleClickOutsideTabs(); - } -} - - -void -TabContainerView::MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage) -{ - _MouseMoved(where, transit, dragMessage); -} - - -void -TabContainerView::DoLayout() -{ - BGroupView::DoLayout(); - - BPoint where; - uint32 buttons; - GetMouse(&where, &buttons, false); - if (Bounds().Contains(where)) - _MouseMoved(where, B_INSIDE_VIEW, NULL); -} - -void -TabContainerView::AddTab(const char* label, int32 index) -{ - TabView* tab; - if (fController) - tab = fController->CreateTabView(); - else - tab = new TabView(); - tab->SetLabel(label); - AddTab(tab, index); -} - - -void -TabContainerView::AddTab(TabView* tab, int32 index) -{ - tab->SetContainerView(this); - - if (index == -1) - index = GroupLayout()->CountItems() - 1; - - bool hasFrames = fController != NULL && fController->HasFrames(); - bool isFirst = index == 0 && hasFrames; - bool isLast = index == GroupLayout()->CountItems() - 1 && hasFrames; - bool isFront = fSelectedTab == NULL; - tab->Update(isFirst, isLast, isFront); - - GroupLayout()->AddItem(index, tab->LayoutItem()); - - if (isFront) - SelectTab(tab); - if (isLast) { - TabLayoutItem* item - = dynamic_cast<TabLayoutItem*>(GroupLayout()->ItemAt(index - 1)); - if (item) - item->Parent()->SetIsLast(false); - } -} - -TabView* -TabContainerView::RemoveTab(int32 index) -{ - TabLayoutItem* item - = dynamic_cast<TabLayoutItem*>(GroupLayout()->RemoveItem(index)); - - if (!item) - return NULL; - - BRect dirty(Bounds()); - dirty.left = item->Frame().left; - TabView* removedTab = item->Parent(); - removedTab->SetContainerView(NULL); - - if (removedTab == fLastMouseEventTab) - fLastMouseEventTab = NULL; - - // Update tabs after or before the removed tab. - bool hasFrames = fController != NULL && fController->HasFrames(); - item = dynamic_cast<TabLayoutItem*>(GroupLayout()->ItemAt(index)); - if (item) { - // This tab is behind the removed tab. - TabView* tab = item->Parent(); - tab->Update(index == 0 && hasFrames, - index == GroupLayout()->CountItems() - 2 && hasFrames, - tab == fSelectedTab); - if (removedTab == fSelectedTab) { - fSelectedTab = NULL; - SelectTab(tab); - } else if (fController && tab == fSelectedTab) - fController->TabSelected(index); - } else { - // The removed tab was the last tab. - item = dynamic_cast<TabLayoutItem*>(GroupLayout()->ItemAt(index - 1)); - if (item) { - TabView* tab = item->Parent(); - tab->Update(index == 0 && hasFrames, - index == GroupLayout()->CountItems() - 2 && hasFrames, - tab == fSelectedTab); - if (removedTab == fSelectedTab) { - fSelectedTab = NULL; - SelectTab(tab); - } - } - } - - Invalidate(dirty); - - return removedTab; -} - - -TabView* -TabContainerView::TabAt(int32 index) const -{ - TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( - GroupLayout()->ItemAt(index)); - if (item) - return item->Parent(); - return NULL; -} - - -int32 -TabContainerView::IndexOf(TabView* tab) const -{ - return GroupLayout()->IndexOfItem(tab->LayoutItem()); -} - - -void -TabContainerView::SelectTab(int32 index) -{ - TabView* tab = NULL; - TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( - GroupLayout()->ItemAt(index)); - if (item) - tab = item->Parent(); - - SelectTab(tab); -} - -void -TabContainerView::SelectTab(TabView* tab) -{ - if (tab == fSelectedTab) - return; - - if (fSelectedTab) - fSelectedTab->SetIsFront(false); - - fSelectedTab = tab; - - if (fSelectedTab) - fSelectedTab->SetIsFront(true); - - if (fController != NULL) { - int32 index = -1; - if (fSelectedTab != NULL) - index = GroupLayout()->IndexOfItem(tab->LayoutItem()); - - fController->TabSelected(index); - } -} - - -void -TabContainerView::SetTabLabel(int32 tabIndex, const char* label) -{ - TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( - GroupLayout()->ItemAt(tabIndex)); - if (item == NULL) - return; - - item->Parent()->SetLabel(label); -} - - -TabView* -TabContainerView::_TabAt(const BPoint& where) const -{ - BGroupLayout* layout = GroupLayout(); - int32 count = layout->CountItems() - 1; - for (int32 i = 0; i < count; i++) { - TabLayoutItem* item = dynamic_cast<TabLayoutItem*>( - layout->ItemAt(i)); - if (item && item->Frame().Contains(where)) - return item->Parent(); - } - return NULL; -} - - -void -TabContainerView::_MouseMoved(BPoint where, uint32 _transit, - const BMessage* dragMessage) -{ - TabView* tab = _TabAt(where); - if (fMouseDown) { - uint32 transit = tab == fLastMouseEventTab - ? B_INSIDE_VIEW : B_OUTSIDE_VIEW; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, transit, dragMessage); - return; - } - - if (fLastMouseEventTab && fLastMouseEventTab == tab) - fLastMouseEventTab->MouseMoved(where, B_INSIDE_VIEW, dragMessage); - else { - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, B_EXITED_VIEW, dragMessage); - fLastMouseEventTab = tab; - if (fLastMouseEventTab) - fLastMouseEventTab->MouseMoved(where, B_ENTERED_VIEW, dragMessage); - } -} +#include "TabContainerView.h" // #pragma mark - TabView TabView::TabView() - : fContainerView(NULL) - , fLayoutItem(new TabLayoutItem(this)) - , fLabel() + : + fContainerView(NULL), + fLayoutItem(new TabLayoutItem(this)), + fLabel() { } + TabView::~TabView() { // The layout item is deleted for us by the layout which contains it. @@ -523,19 +62,25 @@ delete fLayoutItem; } -BSize TabView::MinSize() + +BSize +TabView::MinSize() { BSize size(MaxSize()); size.width = 100.0f; return size; } -BSize TabView::PreferredSize() + +BSize +TabView::PreferredSize() { return MaxSize(); } -BSize TabView::MaxSize() + +BSize +TabView::MaxSize() { float extra = be_control_look->DefaultLabelSpacing(); float labelWidth = fContainerView->StringWidth(fLabel.String()) + 2 * extra; @@ -543,7 +88,9 @@ return BSize(labelWidth, _LabelHeight() + extra); } -void TabView::Draw(BRect updateRect) + +void +TabView::Draw(BRect updateRect) { BRect frame(fLayoutItem->Frame()); if (fIsFront) { @@ -572,7 +119,9 @@ fIsFront); } -void TabView::DrawBackground(BView* owner, BRect frame, const BRect& updateRect, + +void +TabView::DrawBackground(BView* owner, BRect frame, const BRect& updateRect, bool isFirst, bool isLast, bool isFront) { rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); @@ -591,7 +140,9 @@ } } -void TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, + +void +TabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, bool isFirst, bool isLast, bool isFront) { rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); @@ -599,63 +150,83 @@ base, 0, BAlignment(B_ALIGN_LEFT, B_ALIGN_MIDDLE)); } -void TabView::MouseDown(BPoint where, uint32 buttons) + +void +TabView::MouseDown(BPoint where, uint32 buttons) { fContainerView->SelectTab(this); } -void TabView::MouseUp(BPoint where) + +void +TabView::MouseUp(BPoint where) { } -void TabView::MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage) + +void +TabView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage) { } -void TabView::SetIsFront(bool isFront) + +void +TabView::SetIsFront(bool isFront) { Update(fIsFirst, fIsLast, isFront); } -bool TabView::IsFront() const + +bool +TabView::IsFront() const { return fIsFront; } -void TabView::SetIsLast(bool isLast) + +void +TabView::SetIsLast(bool isLast) { Update(fIsFirst, isLast, fIsFront); } -void TabView::Update(bool isFirst, bool isLast, bool isFront) + +void +TabView::Update(bool isFirst, bool isLast, bool isFront) { if (fIsFirst == isFirst && fIsLast == isLast && fIsFront == isFront) return; fIsFirst = isFirst; fIsLast = isLast; fIsFront = isFront; - BRect frame = fLayoutItem->Frame(); - frame.bottom++; - fContainerView->Invalidate(frame); + + fLayoutItem->InvalidateContainer(); } -void TabView::SetContainerView(TabContainerView* containerView) + +void +TabView::SetContainerView(TabContainerView* containerView) { fContainerView = containerView; } -TabContainerView* TabView::ContainerView() const + +TabContainerView* +TabView::ContainerView() const { return fContainerView; } -BLayoutItem* TabView::LayoutItem() const + +BLayoutItem* +TabView::LayoutItem() const { return fLayoutItem; } -void TabView::SetLabel(const char* label) + +void +TabView::SetLabel(const char* label) { if (fLabel == label) return; @@ -663,7 +234,9 @@ fLayoutItem->InvalidateLayout(); } -const BString& TabView::Label() const + +const BString& +TabView::Label() const { return fLabel; } @@ -676,757 +249,118 @@ } -float TabView::_LabelHeight() const +float +TabView::_LabelHeight() const { font_height fontHeight; fContainerView->GetFontHeight(&fontHeight); return ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); } -// #pragma mark - TabLayoutItem - -TabLayoutItem::TabLayoutItem(TabView* parent) - : fParent(parent) -{ -} - -bool TabLayoutItem::IsVisible() -{ - return !fParent->ContainerView()->IsHidden(fParent->ContainerView()); -} - -void TabLayoutItem::SetVisible(bool visible) -{ - // not allowed -} -BRect TabLayoutItem::Frame() -{ - return fFrame; -} - -void TabLayoutItem::SetFrame(BRect frame) -{ - BRect dirty = fFrame; - fFrame = frame; - dirty = dirty | fFrame; - // Invalidate more than necessary, to help the TabContainerView - // redraw the parts outside any tabs... - dirty.bottom++; - dirty.right++; - fParent->ContainerView()->Invalidate(dirty); -} - -BView* TabLayoutItem::View() -{ - return NULL; -} - -BSize TabLayoutItem::BaseMinSize() -{ - return fParent->MinSize(); -} - -BSize TabLayoutItem::BaseMaxSize() -{ - return fParent->MaxSize(); -} - -BSize TabLayoutItem::BasePreferredSize() -{ - return fParent->PreferredSize(); -} - -BAlignment TabLayoutItem::BaseAlignment() -{ - return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); -} - -TabView* TabLayoutItem::Parent() const -{ - return fParent; -} - - -// #pragma mark - TabManagerController - - -class TabManagerController : public TabContainerView::Controller { -public: - TabManagerController(TabManager* manager); - - virtual ~TabManagerController(); - - virtual void TabSelected(int32 index) - { - fManager->SelectTab(index); - } - - virtual bool HasFrames() - { - return false; - } - - virtual TabView* CreateTabView(); - - virtual void DoubleClickOutsideTabs(); - - void CloseTab(int32 index); - - void SetCloseButtonsAvailable(bool available) - { - fCloseButtonsAvailable = available; - } - - bool CloseButtonsAvailable() const - { - return fCloseButtonsAvailable; - } - - void SetDoubleClickOutsideTabsMessage(const BMessage& message, - const BMessenger& target); - -private: - TabManager* fManager; - bool fCloseButtonsAvailable; - BMessage* fDoubleClickOutsideTabsMessage; - BMessenger fTarget; -}; - - -// #pragma mark - WebTabView - - -class WebTabView : public TabView { -public: - WebTabView(TabManagerController* controller); - ~WebTabView(); - - virtual BSize MaxSize(); - - virtual void DrawContents(BView* owner, BRect frame, const BRect& updateRect, - bool isFirst, bool isLast, bool isFront); - - virtual void MouseDown(BPoint where, uint32 buttons); - virtual void MouseUp(BPoint where); - virtual void MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage); - - void SetIcon(const BBitmap* icon); - -private: - void _DrawCloseButton(BView* owner, BRect& frame, const BRect& updateRect, - bool isFirst, bool isLast, bool isFront); - BRect _CloseRectFrame(BRect frame) const; - -private: - BBitmap* fIcon; - TabManagerController* fController; - bool fOverCloseRect; - bool fClicked; -}; +// #pragma mark - TabLayoutItem -WebTabView::WebTabView(TabManagerController* controller) +TabLayoutItem::TabLayoutItem(TabView* parent) : - TabView(), - fIcon(NULL), - fController(controller), - fOverCloseRect(false), - fClicked(false) -{ -} - - -WebTabView::~WebTabView() -{ - delete fIcon; -} - - -static const int kIconSize = 18; -static const int kIconInset = 3; - - -BSize -WebTabView::MaxSize() + fParent(parent), + fVisible(true) { - // Account for icon. - BSize size(TabView::MaxSize()); - size.height = max_c(size.height, kIconSize + kIconInset * 2); - if (fIcon) - size.width += kIconSize + kIconInset * 2; - // Account for close button. - size.width += size.height; - return size; } -void -WebTabView::DrawContents(BView* owner, BRect frame, const BRect& updateRect, - bool isFirst, bool isLast, bool isFront) +bool +TabLayoutItem::IsVisible() { - if (fController->CloseButtonsAvailable()) - _DrawCloseButton(owner, frame, updateRect, isFirst, isLast, isFront); - - if (fIcon) { - BRect iconBounds(0, 0, kIconSize - 1, kIconSize - 1); - // clip to icon bounds, if they are smaller - if (iconBounds.Contains(fIcon->Bounds())) - iconBounds = fIcon->Bounds(); - else { - // Try to scale down the icon by an even factor so the - // final size is between 14 and 18 pixel size. If this fails, - // the icon will simply be displayed at 18x18. - float scale = 2; - while ((fIcon->Bounds().Width() + 1) / scale > kIconSize) - scale *= 2; - if ((fIcon->Bounds().Width() + 1) / scale >= kIconSize - 4 - && (fIcon->Bounds().Height() + 1) / scale >= kIconSize - 4 - && (fIcon->Bounds().Height() + 1) / scale <= kIconSize) { - iconBounds.right = (fIcon->Bounds().Width() + 1) / scale - 1; - iconBounds.bottom = (fIcon->Bounds().Height() + 1) / scale - 1; - } - } - BPoint iconPos(frame.left + kIconInset - 1, - frame.top + floorf((frame.Height() - iconBounds.Height()) / 2)); - iconBounds.OffsetTo(iconPos); - owner->SetDrawingMode(B_OP_ALPHA); - owner->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); - owner->DrawBitmap(fIcon, fIcon->Bounds(), iconBounds, - B_FILTER_BITMAP_BILINEAR); - owner->SetDrawingMode(B_OP_COPY); - frame.left = frame.left + kIconSize + kIconInset * 2; - } - - TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, isFront); -} - - -void -WebTabView::MouseDown(BPoint where, uint32 buttons) -{ - if (buttons & B_TERTIARY_MOUSE_BUTTON) { - fController->CloseTab(ContainerView()->IndexOf(this)); - return; - } - - BRect closeRect = _CloseRectFrame(Frame()); - if (!fController->CloseButtonsAvailable() || !closeRect.Contains(where)) { - TabView::MouseDown(where, buttons); - return; - } - - fClicked = true; - ContainerView()->Invalidate(closeRect); + return fVisible; } void -WebTabView::MouseUp(BPoint where) +TabLayoutItem::SetVisible(bool visible) { - if (!fClicked) { - TabView::MouseUp(where); + if (fVisible == visible) return; - } - - fClicked = false; - - if (_CloseRectFrame(Frame()).Contains(where)) - fController->CloseTab(ContainerView()->IndexOf(this)); -} - - -void -WebTabView::MouseMoved(BPoint where, uint32 transit, - const BMessage* dragMessage) -{ - if (fController->CloseButtonsAvailable()) { - BRect closeRect = _CloseRectFrame(Frame()); - bool overCloseRect = closeRect.Contains(where); - if (overCloseRect != fOverCloseRect) { - fOverCloseRect = overCloseRect; - ContainerView()->Invalidate(closeRect); - } - } - - TabView::MouseMoved(where, transit, dragMessage); -} + fVisible = visible; -void -WebTabView::SetIcon(const BBitmap* icon) -{ - delete fIcon; - if (icon) - fIcon = new BBitmap(icon); - else - fIcon = NULL; - LayoutItem()->InvalidateLayout(); + InvalidateContainer(); + fParent->ContainerView()->InvalidateLayout(); } BRect -WebTabView::_CloseRectFrame(BRect frame) const +TabLayoutItem::Frame() { - frame.left = frame.right - frame.Height(); - return frame; -} - - -void WebTabView::_DrawCloseButton(BView* owner, BRect& frame, - const BRect& updateRect, bool isFirst, bool isLast, bool isFront) -{ - BRect closeRect = _CloseRectFrame(frame); - frame.right = closeRect.left - be_control_look->DefaultLabelSpacing(); - - closeRect.left = (closeRect.left + closeRect.right) / 2 - 3; - closeRect.right = closeRect.left + 6; - closeRect.top = (closeRect.top + closeRect.bottom) / 2 - 3; - closeRect.bottom = closeRect.top + 6; - - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - float tint = B_DARKEN_1_TINT; - if (!IsFront()) { - base = tint_color(base, tint); - tint *= 1.02; - } - - if (fOverCloseRect) - tint *= 1.2; - - if (fClicked && fOverCloseRect) { - BRect buttonRect(closeRect.InsetByCopy(-4, -4)); - be_control_look->DrawButtonFrame(owner, buttonRect, updateRect, - base, base, - BControlLook::B_ACTIVATED | BControlLook::B_BLEND_FRAME); - be_control_look->DrawButtonBackground(owner, buttonRect, updateRect, - base, BControlLook::B_ACTIVATED); - tint *= 1.2; - closeRect.OffsetBy(1, 1); - } - - base = tint_color(base, tint); - owner->SetHighColor(base); - owner->SetPenSize(2); - owner->StrokeLine(closeRect.LeftTop(), closeRect.RightBottom()); - owner->StrokeLine(closeRect.LeftBottom(), closeRect.RightTop()); - owner->SetPenSize(1); -} - - -// #pragma mark - TabManagerController - - -TabManagerController::TabManagerController(TabManager* manager) - : - fManager(manager), - fCloseButtonsAvailable(false), - fDoubleClickOutsideTabsMessage(NULL) -{ -} - - -TabManagerController::~TabManagerController() -{ - delete fDoubleClickOutsideTabsMessage; -} - - -TabView* -TabManagerController::CreateTabView() -{ - return new WebTabView(this); -} - - -void -TabManagerController::DoubleClickOutsideTabs() -{ - fTarget.SendMessage(fDoubleClickOutsideTabsMessage); -} - - -void -TabManagerController::CloseTab(int32 index) -{ - fManager->CloseTab(index); -} - - -void -TabManagerController::SetDoubleClickOutsideTabsMessage(const BMessage& message, - const BMessenger& target) -{ - delete fDoubleClickOutsideTabsMessage; - fDoubleClickOutsideTabsMessage = new BMessage(message); - fTarget = target; -} - - -// #pragma mark - TabButtonContainer - - -class TabButtonContainer : public BGroupView { -public: - TabButtonContainer() - : BGroupView(B_HORIZONTAL) - { - SetFlags(Flags() | B_WILL_DRAW); - SetViewColor(B_TRANSPARENT_COLOR); - SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); - GroupLayout()->SetInsets(0, 6, 0, 0); - } - - virtual void Draw(BRect updateRect) - { - BRect bounds(Bounds()); - rgb_color base = LowColor(); - be_control_look->DrawInactiveTab(this, bounds, updateRect, - base, 0, BControlLook::B_TOP_BORDER); - } -}; - - -// #pragma mark - TabButton - - -class TabButton : public BButton { -public: - TabButton(BMessage* message) - : BButton("", message) - { - } - - virtual BSize MinSize() - { - return BSize(12, 12); - } - - virtual BSize MaxSize() - { - return BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); - } - - virtual BSize PreferredSize() - { - return MinSize(); - } - - virtual void Draw(BRect updateRect) - { - BRect bounds(Bounds()); - rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); - SetHighColor(tint_color(base, B_DARKEN_2_TINT)); - StrokeLine(bounds.LeftBottom(), bounds.RightBottom()); - bounds.bottom--; - uint32 flags = be_control_look->Flags(this); - uint32 borders = BControlLook::B_TOP_BORDER - | BControlLook::B_BOTTOM_BORDER; - be_control_look->DrawInactiveTab(this, bounds, updateRect, base, - flags, borders); - if (IsEnabled()) { - rgb_color button = tint_color(base, 1.07); - be_control_look->DrawButtonBackground(this, bounds, updateRect, - button, flags, 0); - } - - bounds.left = (bounds.left + bounds.right) / 2 - 6; - bounds.top = (bounds.top + bounds.bottom) / 2 - 6; - bounds.right = bounds.left + 12; - bounds.bottom = bounds.top + 12; - DrawSymbol(bounds, updateRect, base); - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - } -}; - - -class ScrollLeftTabButton : public TabButton { -public: - ScrollLeftTabButton(BMessage* message) - : TabButton(message) - { - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_LEFT_ARROW, 0, B_DARKEN_4_TINT); - } -}; - - -class ScrollRightTabButton : public TabButton { -public: - ScrollRightTabButton(BMessage* message) - : TabButton(message) - { - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_RIGHT_ARROW, 0, B_DARKEN_4_TINT); - } -}; - - -class NewTabButton : public TabButton { -public: - NewTabButton(BMessage* message) - : TabButton(message) - { - SetToolTip("New tab (Cmd-T)"); - } - - virtual BSize MinSize() - { - return BSize(18, 12); - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - SetHighColor(tint_color(base, B_DARKEN_4_TINT)); - float inset = 3; - frame.InsetBy(2, 2); - frame.top++; - frame.left++; - FillRoundRect(BRect(frame.left, frame.top + inset, - frame.right, frame.bottom - inset), 1, 1); - FillRoundRect(BRect(frame.left + inset, frame.top, - frame.right - inset, frame.bottom), 1, 1); - } -}; - - -class TabMenuTabButton : public TabButton { -public: - TabMenuTabButton(BMessage* message) - : TabButton(message) - { - } - - virtual BSize MinSize() - { - return BSize(18, 12); - } - - virtual void DrawSymbol(BRect frame, const BRect& updateRect, - const rgb_color& base) - { - be_control_look->DrawArrowShape(this, frame, updateRect, - base, BControlLook::B_DOWN_ARROW, 0, B_DARKEN_4_TINT); - } -}; - - -// #pragma mark - TabManager - - -TabManager::TabManager(const BMessenger& target, BMessage* newTabMessage) - : - fController(new TabManagerController(this)), - fTarget(target) -{ - fController->SetDoubleClickOutsideTabsMessage(*newTabMessage, - be_app_messenger); - - fContainerView = new BView("web view container", 0); - fCardLayout = new BCardLayout(); - fContainerView->SetLayout(fCardLayout); - - fTabContainerView = new TabContainerView(fController); - fTabContainerGroup = new BGroupView(B_HORIZONTAL); - fTabContainerGroup->GroupLayout()->SetInsets(0, 3, 0, 0); - -#if INTEGRATE_MENU_INTO_TAB_BAR - fMenu = new BMenu("Menu"); - BMenuBar* menuBar = new BMenuBar("Menu bar"); - menuBar->AddItem(fMenu); - TabButtonContainer* menuBarContainer = new TabButtonContainer(); - menuBarContainer->GroupLayout()->AddView(menuBar); - fTabContainerGroup->GroupLayout()->AddView(menuBarContainer, 0.0f); -#endif - - fTabContainerGroup->GroupLayout()->AddView(fTabContainerView); -// fTabContainerGroup->GroupLayout()->AddView(new ScrollLeftTabButton(NULL), 0.0f); -// fTabContainerGroup->GroupLayout()->AddView(new ScrollRightTabButton(NULL), 0.0f); - NewTabButton* newTabButton = new NewTabButton(newTabMessage); - newTabButton->SetTarget(be_app); - fTabContainerGroup->GroupLayout()->AddView(newTabButton, 0.0f); -// fTabContainerGroup->GroupLayout()->AddView(new TabMenuTabButton(NULL), 0.0f); -} - - -TabManager::~TabManager() -{ - delete fController; + return fFrame; } void -TabManager::SetTarget(const BMessenger& target) +TabLayoutItem::SetFrame(BRect frame) { - fTarget = target; -} - - -const BMessenger& -TabManager::Target() const -{ - return fTarget; -} - - -#if INTEGRATE_MENU_INTO_TAB_BAR -BMenu* -TabManager::Menu() const -{ - return fMenu; -} -#endif - - -BView* -TabManager::TabGroup() const -{ - return fTabContainerGroup; -} - - -BView* -TabManager::ContainerView() const -{ - return fContainerView; + BRect dirty = fFrame; + fFrame = frame; + dirty = dirty | fFrame; + InvalidateContainer(dirty); } BView* -TabManager::ViewForTab(int32 tabIndex) const +TabLayoutItem::View() { - BLayoutItem* item = fCardLayout->ItemAt(tabIndex); - if (item != NULL) - return item->View(); return NULL; } -int32 -TabManager::TabForView(const BView* containedView) const -{ - int32 count = fCardLayout->CountItems(); - for (int32 i = 0; i < count; i++) { - BLayoutItem* item = fCardLayout->ItemAt(i); - if (item->View() == containedView) - return i; - } - return -1; -} - - -void -TabManager::SelectTab(int32 tabIndex) -{ - fCardLayout->SetVisibleItem(tabIndex); - fTabContainerView->SelectTab(tabIndex); - - BMessage message(TAB_CHANGED); - message.AddInt32("tab index", tabIndex); - fTarget.SendMessage(&message); -} - - -void -TabManager::SelectTab(const BView* containedView) -{ - int32 tabIndex = TabForView(containedView); - if (tabIndex > 0) - SelectTab(tabIndex); -} - - -int32 -TabManager::SelectedTabIndex() const -{ - return fCardLayout->VisibleIndex(); -} - - -void -TabManager::CloseTab(int32 tabIndex) +BSize +TabLayoutItem::BaseMinSize() { - BMessage message(CLOSE_TAB); - message.AddInt32("tab index", tabIndex); - fTarget.SendMessage(&message); + return fParent->MinSize(); } -void -TabManager::AddTab(BView* view, const char* label, int32 index) +BSize +TabLayoutItem::BaseMaxSize() { - fTabContainerView->AddTab(label, index); - fCardLayout->AddView(index, view); + return fParent->MaxSize(); } -BView* -TabManager::RemoveTab(int32 index) +BSize +TabLayoutItem::BasePreferredSize() { - // It's important to remove the view first, since - // removing the tab will preliminary mess with the selected tab - // and then item count of card layout and tab container will not - // match yet. - BLayoutItem* item = fCardLayout->RemoveItem(index); - if (item == NULL) - return NULL; - - TabView* tab = fTabContainerView->RemoveTab(index); - delete tab; - - BView* view = item->View(); - delete item; - return view; + return fParent->PreferredSize(); } -int32 -TabManager::CountTabs() const +BAlignment +TabLayoutItem::BaseAlignment() { - return fCardLayout->CountItems(); + return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); } -void -TabManager::SetTabLabel(int32 tabIndex, const char* label) +TabView* +TabLayoutItem::Parent() const { - fTabContainerView->SetTabLabel(tabIndex, label); + return fParent; } void -TabManager::SetTabIcon(const BView* containedView, const BBitmap* icon) +TabLayoutItem::InvalidateContainer() { - WebTabView* tab = dynamic_cast<WebTabView*>(fTabContainerView->TabAt( - TabForView(containedView))); - if (tab) - tab->SetIcon(icon); + InvalidateContainer(Frame()); } void -TabManager::SetCloseButtonsAvailable(bool available) +TabLayoutItem::InvalidateContainer(BRect frame) { - if (available == fController->CloseButtonsAvailable()) - return; - fController->SetCloseButtonsAvailable(available); - fTabContainerView->Invalidate(); + // Invalidate more than necessary, to help the TabContainerView + // redraw the parts outside any tabs... + frame.bottom++; + frame.right++; + fParent->ContainerView()->Invalidate(frame); } - - Copied and modified: webkit/trunk/WebKit/haiku/WebPositive/tabview/TabView.h (from r403, webkit/trunk/WebKit/haiku/WebPositive/WebTabView.h) ============================================================================== --- webkit/trunk/WebKit/haiku/WebPositive/WebTabView.h Thu Apr 8 15:52:28 2010 (r403, copy source) +++ webkit/trunk/WebKit/haiku/WebPositive/tabview/TabView.h Thu Apr 15 12:19:16 2010 (r416) @@ -24,70 +24,99 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#ifndef TAB_VIEW_H +#define TAB_VIEW_H -#ifndef TAB_MANAGER_H -#define TAB_MANAGER_H +#include <AbstractLayoutItem.h> +#include <Rect.h> +#include <String.h> -#include <Messenger.h> -#include <TabView.h> -enum { - TAB_CHANGED = 'tcha', - CLOSE_TAB = 'cltb' -}; - -class BBitmap; -class BCardLayout; -class BGroupView; -class BMenu; +class BMessage; +class BView; class TabContainerView; -class TabManagerController; +class TabLayoutItem; + -class TabManager { +class TabView { public: - TabManager(const BMessenger& target, - BMessage* newTabMessage); - virtual ~TabManager(); - - void SetTarget(const BMessenger& target); - const BMessenger& Target() const; - -#if INTEGRATE_MENU_INTO_TAB_BAR - BMenu* Menu() const; -#endif - - BView* TabGroup() const; - BView* ContainerView() const; - - BView* ViewForTab(int32 tabIndex) const; - int32 TabForView(const BView* containedView) const; - - void SelectTab(int32 tabIndex); - void SelectTab(const BView* containedView); - int32 SelectedTabIndex() const; - void CloseTab(int32 tabIndex); - - void AddTab(BView* view, const char* label, - int32 index = -1); - BView* RemoveTab(int32 index); - int32 CountTabs() const; - - void SetTabLabel(int32 tabIndex, const char* label); - void SetTabIcon(const BView* containedView, - const BBitmap* icon); - void SetCloseButtonsAvailable(bool available); + TabView(); + virtual ~TabView(); + + virtual BSize MinSize(); + virtual BSize PreferredSize(); + virtual BSize MaxSize(); + + void Draw(BRect updateRect); + virtual void DrawBackground(BView* owner, BRect frame, + const BRect& updateRect, bool isFirst, + bool isLast, bool isFront); + virtual void DrawContents(BView* owner, BRect frame, + const BRect& updateRect, bool isFirst, + bool isLast, bool isFront); + + virtual void MouseDown(BPoint where, uint32 buttons); + virtual void MouseUp(BPoint where); + virtual void MouseMoved(BPoint where, uint32 transit, + const BMessage* dragMessage); + + void SetIsFront(bool isFront); + bool IsFront() const; + void SetIsLast(bool isLast); + virtual void Update(bool isFirst, bool isLast, + bool isFront); + + BLayoutItem* LayoutItem() const; + void SetContainerView( + TabContainerView* containerView); + TabContainerView* ContainerView() const; + + void SetLabel(const char* label); + const BString& Label() const; + + BRect Frame() const; private: -#if INTEGRATE_MENU_INTO_TAB_BAR - BMenu* fMenu; -#endif - BGroupView* fTabContainerGroup; - TabContainerView* fTabContainerView; - BView* fContainerView; - BCardLayout* fCardLayout; - TabManagerController* fController; + float _LabelHeight() const; - BMessenger fTarget; +private: + TabContainerView* fContainerView; + TabLayoutItem* fLayoutItem; + + BString fLabel; + + bool fIsFirst; + bool fIsLast; + bool fIsFront; }; -#endif // TAB_MANAGER_H + +class TabLayoutItem : public BAbstractLayoutItem { +public: + TabLayoutItem(TabView* parent); + + virtual bool IsVisible(); + virtual void SetVisible(bool visible); + + virtual BRect Frame(); + virtual void SetFrame(BRect frame); + + virtual BView* View(); + + virtual BSize BaseMinSize(); + virtual BSize BaseMaxSize(); + virtual BSize BasePreferredSize(); + virtual BAlignment BaseAlignment(); + + TabView* Parent() const; + void InvalidateContainer(); + void InvalidateContainer(BRect frame); +private: + TabView* fParent; + BRect fFrame; + bool fVisible; +}; + + + +#endif // TAB_VIEW_H