[haiku-webkit-commits] r228 - webkit/trunk/WebKit/haiku/HaikuLauncher

  • From: webkit@xxxxxxxxxxxxxxx
  • To: haiku-webkit-commits@xxxxxxxxxxxxx
  • Date: Fri, 26 Feb 2010 19:02:24 +0000

Author: stippi
Date: Fri Feb 26 19:02:24 2010
New Revision: 228
URL: http://mmlr.dyndns.org/changeset/228

Log:
Implemented a completely new tab view framework:
* Tabs are only visible when there are more than one.
* Tabs have close buttons.
* Much more flexible, adding scrolling and left/right buttons when there are
  more tabs than room will be easy. Also drag&drop of tabs.
I've tested this quite a bit, hopefully there are no regressions.

Modified:
   webkit/trunk/WebKit/haiku/HaikuLauncher/LauncherWindow.cpp
   webkit/trunk/WebKit/haiku/HaikuLauncher/LauncherWindow.h
   webkit/trunk/WebKit/haiku/HaikuLauncher/WebTabView.cpp
   webkit/trunk/WebKit/haiku/HaikuLauncher/WebTabView.h

Modified: webkit/trunk/WebKit/haiku/HaikuLauncher/LauncherWindow.cpp
==============================================================================
--- webkit/trunk/WebKit/haiku/HaikuLauncher/LauncherWindow.cpp  Fri Feb 26 
17:04:47 2010        (r227)
+++ webkit/trunk/WebKit/haiku/HaikuLauncher/LauncherWindow.cpp  Fri Feb 26 
19:02:24 2010        (r228)
@@ -77,8 +77,6 @@
     TEXT_HIDE_FIND_GROUP = 'hfnd',
     TEXT_FIND_NEXT = 'fndn',
     TEXT_FIND_PREVIOUS = 'fndp',
-
-    CLOSE_TAB = 'ctab'
 };
 
 using namespace WebCore;
@@ -97,8 +95,7 @@
         B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS)
     , m_downloadListener(downloadListener)
 {
-    m_tabView = new WebTabView("tabview", BMessenger(this));
-    m_tabView->setTarget(BMessenger(this));
+    m_tabManager = new TabManager(BMessenger(this));
 
     if (toolbarPolicy == HaveToolbar) {
         // Menu
@@ -196,6 +193,7 @@
         // Layout
         AddChild(BGroupLayoutBuilder(B_VERTICAL)
             .Add(m_menuBar)
+            .Add(m_tabManager->TabGroup())
             .Add(BGridLayoutBuilder(kElementSpacing, kElementSpacing)
                 .Add(m_BackButton, 0, 0)
                 .Add(m_ForwardButton, 1, 0)
@@ -204,8 +202,8 @@
                 .Add(button, 4, 0)
                 .SetInsets(kInsetSpacing, kInsetSpacing, kInsetSpacing, 
kInsetSpacing)
             )
-//            .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER))
-            .Add(m_tabView)
+            .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER))
+            .Add(m_tabManager->ContainerView())
             .Add(findGroup)
             .Add(new BSeparatorView(B_HORIZONTAL, B_PLAIN_BORDER))
             .Add(BGroupLayoutBuilder(B_HORIZONTAL, kElementSpacing)
@@ -219,6 +217,7 @@
         m_url->MakeFocus(true);
 
         m_findGroup = layoutItemFor(findGroup);
+        m_tabGroup = layoutItemFor(m_tabManager->TabGroup());
     } else {
         m_BackButton = 0;
         m_ForwardButton = 0;
@@ -344,23 +343,28 @@
         be_app->PostMessage(message);
         break;
 
-    case CLOSE_TAB: {
-        if (m_tabView->CountTabs() > 1)
-            delete m_tabView->RemoveTab(m_tabView->Selection());
-        else
+    case CLOSE_TAB:
+        if (m_tabManager->CountTabs() > 1) {
+               int32 index;
+               if (message->FindInt32("tab index", &index) != B_OK)
+                       index = m_tabManager->SelectedTabIndex();
+            delete m_tabManager->RemoveTab(index);
+            updateTabGroupVisibility();
+        } else
             PostMessage(B_QUIT_REQUESTED);
         break;
-    }
 
     case TAB_CHANGED: {
        // This message may be received also when the last tab closed, i.e. 
with index == -1.
-        int32 index = -1;
-        message->FindInt32("index", &index);
-        BWebView* webView = 
dynamic_cast<BWebView*>(m_tabView->ViewForTab(index));
+        int32 index;
+        if (message->FindInt32("tab index", &index) != B_OK)
+            index = -1;
+        BWebView* webView = 
dynamic_cast<BWebView*>(m_tabManager->ViewForTab(index));
+        if (webView == CurrentWebView())
+               break;
         SetCurrentWebView(webView);
-        BTab* tab = m_tabView->TabAt(index);
-        if (tab)
-            updateTitle(tab->Label());
+        if (webView)
+            updateTitle(webView->MainFrameTitle());
         else
             updateTitle("");
         if (webView) {
@@ -384,8 +388,8 @@
 
     // Iterate over all tabs to delete all BWebViews.
     // Do this here, so WebKit tear down happens earlier.
-    while (m_tabView->CountTabs() > 0)
-        delete m_tabView->RemoveTab(0L);
+    while (m_tabManager->CountTabs() > 0)
+        delete m_tabManager->RemoveTab(0L);
     SetCurrentWebView(0);
 
     BMessage message(WINDOW_CLOSED);
@@ -432,21 +436,22 @@
         webView = new BWebView("web view");
     webView->WebPage()->SetDownloadListener(m_downloadListener);
 
-    m_tabView->AddTab(webView);
-    m_tabView->TabAt(m_tabView->CountTabs() - 1)->SetLabel("New tab");
-    // TODO: Remove when BTabView is fixed...
-    m_tabView->Invalidate();
+    m_tabManager->AddTab(webView, "New tab");
 
     if (url.Length())
         webView->LoadURL(url.String());
 
     if (select) {
-        m_tabView->Select(m_tabView->CountTabs() - 1);
+        m_tabManager->SelectTab(m_tabManager->CountTabs() - 1);
         SetCurrentWebView(webView);
         NavigationCapabilitiesChanged(false, false, false, webView);
-        if (m_url)
+        if (m_url) {
+               m_url->SetText(url.String());
             m_url->MakeFocus(true);
+        }
     }
+
+    updateTabGroupVisibility();
 }
 
 // #pragma mark - Notification API
@@ -577,10 +582,9 @@
 
 void LauncherWindow::TitleChanged(const BString& title, BWebView* view)
 {
-    for (int32 i = 0; i < m_tabView->CountTabs(); i++) {
-        if (m_tabView->ViewForTab(i) == view) {
-            m_tabView->TabAt(i)->SetLabel(title);
-            m_tabView->DrawTabs();
+    for (int32 i = 0; i < m_tabManager->CountTabs(); i++) {
+        if (m_tabManager->ViewForTab(i) == view) {
+            m_tabManager->SetTabLabel(i, title);
             break;
         }
     }
@@ -653,3 +657,11 @@
     windowTitle << "HaikuLauncher";
     SetTitle(windowTitle.String());
 }
+
+void LauncherWindow::updateTabGroupVisibility()
+{
+       if (Lock()) {
+           m_tabGroup->SetVisible(m_tabManager->CountTabs() > 1);
+           Unlock();
+       }
+}

Modified: webkit/trunk/WebKit/haiku/HaikuLauncher/LauncherWindow.h
==============================================================================
--- webkit/trunk/WebKit/haiku/HaikuLauncher/LauncherWindow.h    Fri Feb 26 
17:04:47 2010        (r227)
+++ webkit/trunk/WebKit/haiku/HaikuLauncher/LauncherWindow.h    Fri Feb 26 
19:02:24 2010        (r228)
@@ -42,7 +42,7 @@
 class BStringView;
 class BTextControl;
 class IconButton;
-class WebTabView;
+class TabManager;
 class BWebView;
 
 enum ToolbarPolicy {
@@ -93,6 +93,7 @@
     virtual void AuthenticationChallenge(BMessage* challenge);
 
     void updateTitle(const BString &title);
+    void updateTabGroupVisibility();
 
 private:
     BMessenger m_downloadListener;
@@ -106,9 +107,10 @@
     BStringView* m_statusText;
     BStatusBar* m_loadingProgressBar;
     BLayoutItem* m_findGroup;
+    BLayoutItem* m_tabGroup;
     BTextControl* m_findTextControl;
     BCheckBox* m_findCaseSensitiveCheckBox;
-    WebTabView* m_tabView;
+    TabManager* m_tabManager;
 };
 
 #endif // LauncherWindow_h

Modified: webkit/trunk/WebKit/haiku/HaikuLauncher/WebTabView.cpp
==============================================================================
--- webkit/trunk/WebKit/haiku/HaikuLauncher/WebTabView.cpp      Fri Feb 26 
17:04:47 2010        (r227)
+++ webkit/trunk/WebKit/haiku/HaikuLauncher/WebTabView.cpp      Fri Feb 26 
19:02:24 2010        (r228)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2010 Rene Gollent <rene@xxxxxxxxxxx>
+ * Copyright (C) 2010 Stephan Aßmus <superstippi@xxxxxx>
  *
  * All rights reserved.
  *
@@ -27,34 +28,990 @@
 
 #include "WebTabView.h"
 
-#include <GroupLayout.h>
+#include "WebView.h"
+#include <AbstractLayoutItem.h>
+#include <CardLayout.h>
+#include <ControlLook.h>
+#include <GroupView.h>
+#include <SpaceLayoutItem.h>
+#include <Window.h>
+#include <stdio.h>
 
-WebTabView::WebTabView(const char *name, const BMessenger& target)
-    : BTabView(name)
-    , m_target(target)
+
+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);
+       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;
+       };
+
+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);
+
+       void AddTab(const char* label, int32 index = -1);
+       void AddTab(TabView* tab, int32 index = -1);
+       TabView* RemoveTab(int32 index);
+
+       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;
+
+private:
+       TabView* fLastMouseEventTab;
+       bool fMouseDown;
+       TabView* fSelectedTab;
+       Controller* fController;
+};
+
+
+// #pragma mark - TabContainerView
+
+
+static const float kLeftTabInset = 4;
+
+
+TabContainerView::TabContainerView(Controller* controller)
+       :
+       BGroupView(B_HORIZONTAL),
+       fLastMouseEventTab(NULL),
+       fMouseDown(false),
+       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()
+{
+       // TODO: Not so nice, that we take ownership of the controller.
+       delete fController;
+}
+
+
+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)
+{
+       fMouseDown = true;
+       SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS);
+       if (fLastMouseEventTab)
+               fLastMouseEventTab->MouseDown(where);
+}
+
+
+void
+TabContainerView::MouseUp(BPoint where)
+{
+       fMouseDown = false;
+       if (fLastMouseEventTab)
+               fLastMouseEventTab->MouseUp(where);
+}
+
+
+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);
+       }
+}
+
+
+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;
+}
+
+
+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;
+}
+
+
+// #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++;
+       }
+       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);
+       }
+}
+
+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)
+{
+       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
 {
-       SetBorder(B_NO_BORDER);
-       SetFlags(Flags() & ~B_FULL_UPDATE_ON_RESIZE);
+       return fContainerView;
 }
 
-WebTabView::~WebTabView(void)
+BLayoutItem* TabView::LayoutItem() const
 {
+       return fLayoutItem;
 }
 
-void WebTabView::Select(int32 tab)
+void TabView::SetLabel(const char* label)
 {
-    BTabView::Select(tab);
+       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 void TabSelected(int32 index)
+       {
+               fManager->SelectTab(index);
+       }
+
+       virtual bool HasFrames()
+       {
+               return false;
+       }
+
+       virtual TabView* CreateTabView();
+
+       void CloseTab(int32 index);
+
+private:
+       TabManager* fManager;
+};
+
+
+// #pragma mark - WebTabView
+
+
+class WebTabView : public TabView {
+public:
+       WebTabView(TabManagerController* controller);
+
+       virtual BSize MaxSize();
+
+       virtual void DrawContents(BView* owner, BRect frame, const BRect& 
updateRect,
+               bool isFirst, bool isLast, bool isFront);
+
+       virtual void MouseDown(BPoint where);
+       virtual void MouseUp(BPoint where);
+       virtual void MouseMoved(BPoint where, uint32 transit,
+               const BMessage* dragMessage);
+
+private:
+       BRect _CloseRectFrame(BRect frame) const;
+
+private:
+       TabManagerController* fController;
+       bool fOverCloseRect;
+       bool fClicked;
+};
+
+
+WebTabView::WebTabView(TabManagerController* controller)
+       :
+       TabView(),
+       fController(controller),
+       fOverCloseRect(false),
+       fClicked(false)
+{
+}
+
+
+BSize
+WebTabView::MaxSize()
+{
+       // Account for close button.
+       BSize size(TabView::MaxSize());
+       size.width += size.height;
+       return size;
+}
+
+
+void
+WebTabView::DrawContents(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())
+               tint *= 1.02;
+
+       base = tint_color(base, tint);
+
+       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);
+
+       TabView::DrawContents(owner, frame, updateRect, isFirst, isLast, 
isFront);
+}
+
+
+void
+WebTabView::MouseDown(BPoint where)
+{
+       BRect closeRect = _CloseRectFrame(Frame());
+       if (!closeRect.Contains(where)) {
+               TabView::MouseDown(where);
+               return;
+       }
+
+       fClicked = true;
+       ContainerView()->Invalidate(closeRect);
+}
+
+
+void
+WebTabView::MouseUp(BPoint where)
+{
+       if (!fClicked) {
+               TabView::MouseUp(where);
+               return;
+       }
+
+       fClicked = false;
+
+       if (_CloseRectFrame(Frame()).Contains(where))
+               fController->CloseTab(ContainerView()->IndexOf(this));
+}
+
+
+void
+WebTabView::MouseMoved(BPoint where, uint32 transit,
+       const BMessage* dragMessage)
+{
+       BRect closeRect = _CloseRectFrame(Frame());
+       bool overCloseRect = closeRect.Contains(where);
+       if (overCloseRect != fOverCloseRect) {
+               fOverCloseRect = overCloseRect;
+               ContainerView()->Invalidate(closeRect);
+       }
+
+       TabView::MouseMoved(where, transit, dragMessage);
+}
+
+
+BRect
+WebTabView::_CloseRectFrame(BRect frame) const
+{
+       frame.left = frame.right - frame.Height();
+       return frame;
+}
+
+
+// #pragma mark - TabManagerController
+
+
+TabManagerController::TabManagerController(TabManager* manager)
+       :
+       fManager(manager)
+{
+}
+
+
+TabView*
+TabManagerController::CreateTabView()
+{
+       return new WebTabView(this);
+}
+
+
+void
+TabManagerController::CloseTab(int32 index)
+{
+       fManager->CloseTab(index);
+}
+
+
+// #pragma mark - TabManager
+
+
+
+TabManager::TabManager(const BMessenger& target)
+    :
+    fTarget(target)
+{
+       fContainerView = new BView("web view container", 0);
+       fCardLayout = new BCardLayout();
+       fContainerView->SetLayout(fCardLayout);
+
+       fTabContainerView = new TabContainerView(new 
TabManagerController(this));
+       fTabContainerGroup = new BGroupView(B_HORIZONTAL);
+       fTabContainerGroup->GroupLayout()->SetInsets(0, 5, 0, 0);
+       fTabContainerGroup->GroupLayout()->AddView(fTabContainerView);
+}
+
+
+TabManager::~TabManager()
+{
+}
+
+
+void
+TabManager::SetTarget(const BMessenger& target)
+{
+    fTarget = target;
+}
+
+
+const BMessenger&
+TabManager::Target() const
+{
+    return fTarget;
+}
+
+
+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;
+}
+
+
+void
+TabManager::SelectTab(int32 tabIndex)
+{
+       fCardLayout->SetVisibleItem(tabIndex);
+       fTabContainerView->SelectTab(tabIndex);
+
     BMessage message(TAB_CHANGED);
-    message.AddInt32("index", tab);
-    m_target.SendMessage(&message);
+    message.AddInt32("tab index", tabIndex);
+    fTarget.SendMessage(&message);
 }
 
-const BMessenger& WebTabView::target() const
+
+int32
+TabManager::SelectedTabIndex() const
+{
+       return fCardLayout->VisibleIndex();
+}
+
+
+void
+TabManager::CloseTab(int32 tabIndex)
 {
-    return m_target;
+    BMessage message(CLOSE_TAB);
+    message.AddInt32("tab index", tabIndex);
+    fTarget.SendMessage(&message);
 }
 
-void WebTabView::setTarget(const BMessenger& target)
+
+void
+TabManager::AddTab(BView* view, const char* label, int32 index)
 {
-    m_target = target;
+       fTabContainerView->AddTab(label, index);
+       fCardLayout->AddView(index, view);
 }
+
+
+BView*
+TabManager::RemoveTab(int32 index)
+{
+       // 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;
+}
+
+
+int32
+TabManager::CountTabs() const
+{
+       return fCardLayout->CountItems();
+}
+
+
+void
+TabManager::SetTabLabel(int32 tabIndex, const char* label)
+{
+       fTabContainerView->SetTabLabel(tabIndex, label);
+}
+

Modified: webkit/trunk/WebKit/haiku/HaikuLauncher/WebTabView.h
==============================================================================
--- webkit/trunk/WebKit/haiku/HaikuLauncher/WebTabView.h        Fri Feb 26 
17:04:47 2010        (r227)
+++ webkit/trunk/WebKit/haiku/HaikuLauncher/WebTabView.h        Fri Feb 26 
19:02:24 2010        (r228)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Rene Gollent <rene@xxxxxxxxxxx>
+ * Copyright (C) 2010 Stephan Aßmus <superstippi@xxxxxx>
  *
  * All rights reserved.
  *
@@ -25,28 +25,52 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef WebTabView_h
-#define WebTabView_h
+#ifndef TAB_MANAGER_H
+#define TAB_MANAGER_H
 
 #include <Messenger.h>
 #include <TabView.h>
 
 enum {
-    TAB_CHANGED = 'tcha'
+    TAB_CHANGED = 'tcha',
+    CLOSE_TAB = 'cltb'
 };
 
-class WebTabView : public BTabView {
+class BCardLayout;
+class BGroupView;
+class TabContainerView;
+
+class TabManager {
 public:
-    WebTabView(const char *name, const BMessenger& target);
-    virtual ~WebTabView(void);
-    virtual void Select(int32 tab);
+                                                       TabManager(const 
BMessenger& target);
+       virtual                                         ~TabManager();
+
+                       void                            SetTarget(const 
BMessenger& target);
+                       const BMessenger&       Target() const;
+
+                       BView*                          TabGroup() const;
+                       BView*                          ContainerView() const;
+
+                       BView*                          ViewForTab(int32 
tabIndex) const;
 
-    const BMessenger& target() const;
-    void setTarget(const BMessenger& target);
+                       void                            SelectTab(int32 
tabIndex);
+                       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);
 
 private:
-    BMessenger m_target;
+                       BGroupView*                     fTabContainerGroup;
+                       TabContainerView*       fTabContainerView;
+                       BView*                          fContainerView;
+                       BCardLayout*            fCardLayout;
+
+                       BMessenger                      fTarget;
 };
 
-#define WebTabView_h
-#endif // WebTabView_h
+#endif // TAB_MANAGER_H

Other related posts:

  • » [haiku-webkit-commits] r228 - webkit/trunk/WebKit/haiku/HaikuLauncher - webkit