BTRFS: Implement BTree::Path and change _Find.
[haiku.git] / src / apps / terminal / SmartTabView.cpp
blobb7aad69a3f8b16db2228a0c1d845f374cbd907c6
1 /*
2 * Copyright 2007-2010, Haiku. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Stefano Ceccherini (burton666@libero.it)
7 * Ingo Weinhold (ingo_weinhold@gmx.de)
8 */
11 /*! The SmartTabView class is a BTabView descendant that hides the tab bar
12 as long as there is only a single tab.
13 Furthermore, it provides a tab context menu, as well as allowing you to
14 close buttons with the middle mouse button.
18 #include "SmartTabView.h"
20 #include <stdio.h>
22 #include <Catalog.h>
23 #include <Locale.h>
24 #include <Message.h>
25 #include <Messenger.h>
26 #include <Screen.h>
27 #include <ScrollView.h>
28 #include <Window.h>
31 // #pragma mark - SmartTabView
34 SmartTabView::SmartTabView(BRect frame, const char* name, button_width width,
35 uint32 resizingMode, uint32 flags)
37 BTabView(frame, name, width, resizingMode, flags),
38 fInsets(0, 0, 0, 0),
39 fScrollView(NULL),
40 fListener(NULL)
42 // Resize the container view to fill the complete tab view for single-tab
43 // mode. Later, when more than one tab is added, we shrink the container
44 // view again.
45 frame.OffsetTo(B_ORIGIN);
46 ContainerView()->MoveTo(frame.LeftTop());
47 ContainerView()->ResizeTo(frame.Width(), frame.Height());
51 SmartTabView::~SmartTabView()
56 void
57 SmartTabView::SetInsets(float left, float top, float right, float bottom)
59 fInsets.left = left;
60 fInsets.top = top;
61 fInsets.right = right;
62 fInsets.bottom = bottom;
66 void
67 SmartTabView::MouseDown(BPoint point)
69 bool handled = false;
71 if (CountTabs() > 1) {
72 int32 tabIndex = _ClickedTabIndex(point);
73 int32 buttons = 0;
74 int32 clickCount = 0;
75 Window()->CurrentMessage()->FindInt32("buttons", &buttons);
76 Window()->CurrentMessage()->FindInt32("clicks", &clickCount);
78 if ((buttons & B_PRIMARY_MOUSE_BUTTON) != 0 && clickCount == 2) {
79 if (fListener != NULL)
80 fListener->TabDoubleClicked(this, point, tabIndex);
81 } else if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) {
82 if (fListener != NULL)
83 fListener->TabRightClicked(this, point, tabIndex);
84 handled = true;
85 } else if ((buttons & B_TERTIARY_MOUSE_BUTTON) != 0) {
86 if (fListener != NULL)
87 fListener->TabMiddleClicked(this, point, tabIndex);
88 handled = true;
92 if (!handled)
93 BTabView::MouseDown(point);
97 void
98 SmartTabView::AttachedToWindow()
100 BTabView::AttachedToWindow();
104 void
105 SmartTabView::AllAttached()
107 BTabView::AllAttached();
111 void
112 SmartTabView::Select(int32 index)
114 BTabView::Select(index);
115 BView *view = ViewForTab(index);
116 if (view != NULL) {
117 view->MoveTo(fInsets.LeftTop());
118 view->ResizeTo(ContainerView()->Bounds().Width()
119 - fInsets.left - fInsets.right,
120 ContainerView()->Bounds().Height() - fInsets.top - fInsets.bottom);
123 if (fListener != NULL)
124 fListener->TabSelected(this, index);
128 void
129 SmartTabView::AddTab(BView* target, BTab* tab)
131 if (target == NULL)
132 return;
134 BTabView::AddTab(target, tab);
136 if (CountTabs() == 1) {
137 // Call select on the tab, since
138 // we're resizing the contained view
139 // inside that function
140 Select(0);
141 } else if (CountTabs() == 2) {
142 // Need to resize the view, since we're switching from "normal"
143 // to tabbed mode
144 ContainerView()->ResizeBy(0, -TabHeight());
145 ContainerView()->MoveBy(0, TabHeight());
147 // Make sure the content size stays the same, but take special care
148 // of full screen mode
149 BScreen screen(Window());
150 if (Window()->DecoratorFrame().Height() + 2 * TabHeight()
151 < screen.Frame().Height()) {
152 if (Window()->Frame().bottom + TabHeight()
153 > screen.Frame().bottom - 5) {
154 Window()->MoveBy(0, -TabHeight());
157 Window()->ResizeBy(0, TabHeight());
160 // Adapt scroll bar if there is one
161 if (fScrollView != NULL) {
162 BScrollBar* bar = fScrollView->ScrollBar(B_VERTICAL);
163 if (bar != NULL) {
164 bar->ResizeBy(0, -1);
165 bar->MoveBy(0, 1);
169 SetBorder(B_NO_BORDER);
172 Invalidate(TabFrame(CountTabs() - 1).InsetByCopy(-2, -2));
176 BTab*
177 SmartTabView::RemoveTab(int32 index)
179 if (CountTabs() == 2) {
180 // Hide the tab bar again by resizing the container view
182 // Make sure the content size stays the same, but take special care
183 // of full screen mode
184 BScreen screen(Window());
185 if (Window()->DecoratorFrame().Height() + 2 * TabHeight()
186 < screen.Frame().Height()) {
187 if (Window()->Frame().bottom
188 > screen.Frame().bottom - 5 - TabHeight()) {
189 Window()->MoveBy(0, TabHeight());
191 Window()->ResizeBy(0, -TabHeight());
194 // Adapt scroll bar if there is one
195 if (fScrollView != NULL) {
196 BScrollBar* bar = fScrollView->ScrollBar(B_VERTICAL);
197 if (bar != NULL) {
198 bar->ResizeBy(0, 1);
199 bar->MoveBy(0, -1);
203 ContainerView()->MoveBy(0, -TabHeight());
204 ContainerView()->ResizeBy(0, TabHeight());
207 return BTabView::RemoveTab(index);
211 void
212 SmartTabView::MoveTab(int32 index, int32 newIndex)
214 // check the indexes
215 int32 count = CountTabs();
216 if (index == newIndex || index < 0 || newIndex < 0 || index >= count
217 || newIndex >= count) {
218 return;
221 // Remove the tab from its position and add it to the end. Then cycle the
222 // tabs starting after the new position (save the tab already moved) to the
223 // end.
224 BTab* tab = BTabView::RemoveTab(index);
225 BTabView::AddTab(tab->View(), tab);
227 for (int32 i = newIndex; i < count - 1; i++) {
228 tab = BTabView::RemoveTab(newIndex);
229 BTabView::AddTab(tab->View(), tab);
234 BRect
235 SmartTabView::DrawTabs()
237 if (CountTabs() > 1)
238 return BTabView::DrawTabs();
240 return BRect();
244 /*! If you have a vertical scroll view that overlaps with the menu bar, it will
245 be resized automatically when the tabs are hidden/shown.
247 void
248 SmartTabView::SetScrollView(BScrollView* scrollView)
250 fScrollView = scrollView;
254 int32
255 SmartTabView::_ClickedTabIndex(const BPoint& point)
257 if (point.y <= TabHeight()) {
258 for (int32 i = 0; i < CountTabs(); i++) {
259 if (TabFrame(i).Contains(point))
260 return i;
264 return -1;
268 // #pragma mark - Listener
271 SmartTabView::Listener::~Listener()
276 void
277 SmartTabView::Listener::TabSelected(SmartTabView* tabView, int32 index)
282 void
283 SmartTabView::Listener::TabDoubleClicked(SmartTabView* tabView, BPoint point,
284 int32 index)
289 void
290 SmartTabView::Listener::TabMiddleClicked(SmartTabView* tabView, BPoint point,
291 int32 index)
296 void
297 SmartTabView::Listener::TabRightClicked(SmartTabView* tabView, BPoint point,
298 int32 index)