Ticket #13673: 0003-BTabView-implement-drawing-tabs-on-different-borders.patch
File 0003-BTabView-implement-drawing-tabs-on-different-borders.patch, 16.4 KB (added by , 7 years ago) |
---|
-
headers/os/interface/TabView.h
From c600991f9bc034abeccb6e1da0315a5debc7892a Mon Sep 17 00:00:00 2001 From: Kacper Kasper <kacperkasper@gmail.com> Date: Sat, 19 Aug 2017 19:32:31 +0200 Subject: [PATCH 3/3] BTabView: implement drawing tabs on different borders. --- headers/os/interface/TabView.h | 16 +- src/kits/interface/TabView.cpp | 336 ++++++++++++++++++++++++++++++++++------- 2 files changed, 292 insertions(+), 60 deletions(-) diff --git a/headers/os/interface/TabView.h b/headers/os/interface/TabView.h index 1547610d38..2e8d05367c 100644
a b enum tab_position { 19 19 }; 20 20 21 21 22 enum tab_side { 23 B_LEFT_BORDER = 1 << 0, 24 B_RIGHT_BORDER = 1 << 1, 25 B_TOP_BORDER = 1 << 2, 26 B_BOTTOM_BORDER = 1 << 3 27 }; 28 29 22 30 class BTab : public BArchivable { 23 31 public: 24 32 BTab(BView* contentsView = NULL); … … public: 165 173 virtual void SetBorder(border_style borderStyle); 166 174 border_style Border() const; 167 175 176 virtual void SetTabSide(tab_side tabSide); 177 tab_side TabSide() const; 178 168 179 BView* ContainerView() const; 169 180 170 181 int32 CountTabs() const; … … public: 172 183 173 184 private: 174 185 // FBC padding and forbidden methods 175 virtual void _ReservedTabView2();176 virtual void _ReservedTabView3();177 186 virtual void _ReservedTabView4(); 178 187 virtual void _ReservedTabView5(); 179 188 virtual void _ReservedTabView6(); … … private: 205 214 int32 fFocus; 206 215 float fTabOffset; 207 216 border_style fBorderStyle; 217 tab_side fTabSide; 208 218 209 uint32 _reserved[ 10];219 uint32 _reserved[9]; 210 220 }; 211 221 212 222 #endif // _TAB_VIEW_H -
src/kits/interface/TabView.cpp
diff --git a/src/kits/interface/TabView.cpp b/src/kits/interface/TabView.cpp index 1d589b1dd9..c9451eae86 100644
a b BTab::DrawFocusMark(BView* owner, BRect frame) 243 243 owner->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); 244 244 245 245 float offset = IsSelected() ? 3 : 2; 246 owner->StrokeLine(BPoint((frame.left + frame.right - width) / 2.0, 247 frame.bottom - offset), 248 BPoint((frame.left + frame.right + width) / 2.0, 249 frame.bottom - offset)); 246 switch (fTabView->TabSide()) { 247 case B_TOP_BORDER: 248 owner->StrokeLine(BPoint((frame.left + frame.right - width) / 2.0, 249 frame.bottom - offset), 250 BPoint((frame.left + frame.right + width) / 2.0, 251 frame.bottom - offset)); 252 break; 253 case B_BOTTOM_BORDER: 254 owner->StrokeLine(BPoint((frame.left + frame.right - width) / 2.0, 255 frame.top + offset), 256 BPoint((frame.left + frame.right + width) / 2.0, 257 frame.top + offset)); 258 break; 259 case B_LEFT_BORDER: 260 owner->StrokeLine(BPoint(frame.right - offset, 261 (frame.top + frame.bottom - width) / 2.0), 262 BPoint(frame.right - offset, 263 (frame.top + frame.bottom + width) / 2.0)); 264 break; 265 case B_RIGHT_BORDER: 266 owner->StrokeLine(BPoint(frame.left + offset, 267 (frame.top + frame.bottom - width) / 2.0), 268 BPoint(frame.left + offset, 269 (frame.top + frame.bottom + width) / 2.0)); 270 break; 271 } 250 272 } 251 273 252 274 253 275 void 254 276 BTab::DrawLabel(BView* owner, BRect frame) 255 277 { 278 float rotation; 279 BPoint center(frame.left + frame.Width() / 2, 280 frame.top + frame.Height() / 2); 281 switch (fTabView->TabSide()) { 282 case B_TOP_BORDER: 283 case B_BOTTOM_BORDER: 284 rotation = 0.0f; 285 break; 286 case B_LEFT_BORDER: 287 rotation = 270.0f; 288 break; 289 case B_RIGHT_BORDER: 290 rotation = 90.0f; 291 break; 292 } 293 294 if (rotation != 0.0f) { 295 // DrawLabel doesn't allow rendering rotated text 296 // rotate frame first and BAffineTransform will handle the rotation 297 // we can't give "unrotated" frame because it comes from 298 // BTabView::TabFrame and it is also used to handle mouse clicks 299 BRect originalFrame(frame); 300 frame.top = center.y - originalFrame.Width() / 2; 301 frame.bottom = center.y + originalFrame.Width() / 2; 302 frame.left = center.x - originalFrame.Height() / 2; 303 frame.right = center.x + originalFrame.Height() / 2; 304 } 305 306 BAffineTransform transform; 307 transform.RotateBy(center, rotation * M_PI / 180.0f); 308 owner->SetTransform(transform); 256 309 be_control_look->DrawLabel(owner, Label(), frame, frame, 257 310 ui_color(B_PANEL_BACKGROUND_COLOR), 258 311 IsEnabled() ? 0 : BPrivate::BControlLook::B_DISABLED, 259 312 BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER)); 313 owner->SetTransform(BAffineTransform()); 260 314 } 261 315 262 316 … … void 264 318 BTab::DrawTab(BView* owner, BRect frame, tab_position position, bool full) 265 319 { 266 320 rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR); 267 uint32 borders = BControlLook::B_TOP_BORDER 268 | BControlLook::B_BOTTOM_BORDER; 321 uint32 borders; 322 if (fTabView->TabSide() == B_TOP_BORDER 323 || fTabView->TabSide() == B_BOTTOM_BORDER) { 324 borders = BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER; 269 325 270 if (frame.left == owner->Bounds().left)271 borders |= BControlLook::B_LEFT_BORDER;326 if (frame.left == owner->Bounds().left) 327 borders |= BControlLook::B_LEFT_BORDER; 272 328 273 if (frame.right == owner->Bounds().right) 274 borders |= BControlLook::B_RIGHT_BORDER; 329 if (frame.right == owner->Bounds().right) 330 borders |= BControlLook::B_RIGHT_BORDER; 331 } else if (fTabView->TabSide() == B_LEFT_BORDER 332 || fTabView->TabSide() == B_RIGHT_BORDER) { 333 borders = BControlLook::B_LEFT_BORDER | BControlLook::B_RIGHT_BORDER; 334 335 if (frame.top == owner->Bounds().top) 336 borders |= BControlLook::B_TOP_BORDER; 337 338 if (frame.bottom == owner->Bounds().bottom) 339 borders |= BControlLook::B_BOTTOM_BORDER; 340 } 275 341 276 342 if (position == B_TAB_FRONT) { 277 frame.bottom -= 1.0f; 343 switch (fTabView->TabSide()) { 344 case B_TOP_BORDER: 345 frame.bottom -= 1.0f; 346 break; 347 case B_BOTTOM_BORDER: 348 frame.top += 1.0f; 349 break; 350 case B_LEFT_BORDER: 351 frame.right -= 1.0f; 352 break; 353 case B_RIGHT_BORDER: 354 frame.left += 1.0f; 355 break; 356 } 278 357 be_control_look->DrawActiveTab(owner, frame, frame, no_tint, 0, 279 borders );358 borders, fTabView->TabSide()); 280 359 } else { 281 360 be_control_look->DrawInactiveTab(owner, frame, frame, no_tint, 0, 282 borders );361 borders, fTabView->TabSide()); 283 362 } 284 363 364 285 365 DrawLabel(owner, frame); 286 366 } 287 367 … … BTabView::BTabView(BMessage* archive) 365 445 if (archive->FindInt32("_border_style", (int32*)&fBorderStyle) != B_OK) 366 446 fBorderStyle = B_FANCY_BORDER; 367 447 448 if (archive->FindInt32("_tab_side", (int32*)&fTabSide) != B_OK) 449 fTabSide = B_TOP_BORDER; 450 368 451 int32 i = 0; 369 452 BMessage tabMsg; 370 453 … … BTabView::Archive(BMessage* archive, bool deep) const 426 509 result = archive->AddInt32("_sel", fSelection); 427 510 if (result == B_OK && fBorderStyle != B_FANCY_BORDER) 428 511 result = archive->AddInt32("_border_style", fBorderStyle); 512 if (result == B_OK && fTabSide != B_TOP_BORDER) 513 result = archive->AddInt32("_tab_side", fTabSide); 429 514 430 515 if (result == B_OK && deep) { 431 516 for (int32 i = 0; i < CountTabs(); i++) { … … BTabView::KeyDown(const char* bytes, int32 numBytes) 642 727 void 643 728 BTabView::MouseDown(BPoint where) 644 729 { 645 if (where.y > fTabHeight)646 return;647 648 730 for (int32 i = 0; i < CountTabs(); i++) { 649 731 if (TabFrame(i).Contains(where) 650 732 && i != Selection()) { … … BTabView::Draw(BRect updateRect) 800 882 BRect 801 883 BTabView::DrawTabs() 802 884 { 803 // draw an inactive tab frame behind all tabs804 885 BRect bounds(Bounds()); 805 bounds.bottom = fTabHeight; 886 BRect tabsBounds; 887 uint32 borders; 806 888 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); 807 uint32 borders = BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER; 808 if (fBorderStyle == B_NO_BORDER) { 809 // removes left border that is an artifact of DrawInactiveTab() 810 bounds.left -= 1; 811 } else 812 borders |= BControlLook::B_LEFT_BORDER | BControlLook::B_RIGHT_BORDER; 889 if (fTabSide == B_TOP_BORDER || fTabSide == B_BOTTOM_BORDER) { 890 if (fTabSide == B_TOP_BORDER) 891 bounds.bottom = fTabHeight; 892 else 893 bounds.top = bounds.bottom - fTabHeight; 894 tabsBounds = bounds; 895 // make a copy for later 896 897 // draw an inactive tab frame behind all tabs 898 borders = BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER; 899 if (fBorderStyle == B_NO_BORDER) { 900 // removes left border that is an artifact of DrawInactiveTab() 901 bounds.left -= 1; 902 } else { 903 borders |= BControlLook::B_LEFT_BORDER 904 | BControlLook::B_RIGHT_BORDER; 905 } 906 907 // DrawInactiveTab draws 2px border 908 // draw a little wider tab frame to align B_PLAIN_BORDER with it 909 if (fBorderStyle == B_PLAIN_BORDER) { 910 bounds.left -= 1; 911 bounds.right += 1; 912 } 913 } else if(fTabSide == B_LEFT_BORDER || fTabSide == B_RIGHT_BORDER) { 914 if (fTabSide == B_LEFT_BORDER) 915 bounds.right = fTabHeight; 916 else 917 bounds.left = bounds.right - fTabHeight; 918 tabsBounds = bounds; 919 // make a copy for later 920 921 // draw an inactive tab frame behind all tabs 922 borders = BControlLook::B_LEFT_BORDER | BControlLook::B_RIGHT_BORDER; 923 if (fBorderStyle == B_NO_BORDER) { 924 // removes top border that is an artifact of DrawInactiveTab() 925 bounds.top -= 1; 926 } else { 927 borders |= BControlLook::B_TOP_BORDER 928 | BControlLook::B_BOTTOM_BORDER; 929 } 813 930 814 // DrawInactiveTab draws 2px border 815 // draw a little wider tab frame to align B_PLAIN_BORDER with it 816 if (fBorderStyle == B_PLAIN_BORDER) { 817 bounds.left -= 1; 818 bounds.right += 1; 931 // DrawInactiveTab draws 2px border 932 // draw a little wider tab frame to align B_PLAIN_BORDER with it 933 if (fBorderStyle == B_PLAIN_BORDER) { 934 bounds.top -= 1; 935 bounds.bottom += 1; 936 } 819 937 } 820 938 821 be_control_look->DrawInactiveTab(this, bounds, bounds, base, 0, borders); 939 be_control_look->DrawInactiveTab(this, bounds, bounds, base, 0, 940 borders, fTabSide); 822 941 823 942 // draw the tabs on top of the inactive tab bounds 824 float right = 0.0f;825 943 BRect activeTabFrame; 826 944 int32 tabCount = CountTabs(); 827 945 for (int32 i = 0; i < tabCount; i++) { … … BTabView::DrawTabs() 830 948 activeTabFrame = tabFrame; 831 949 832 950 TabAt(i)->DrawTab(this, tabFrame, 833 i == fSelection ? B_TAB_FRONT : (i == 0) ? B_TAB_FIRST : B_TAB_ANY, 951 i == fSelection ? B_TAB_FRONT : 952 (i == 0) ? B_TAB_FIRST : B_TAB_ANY, 834 953 i + 1 != fSelection); 835 right = tabFrame.right;836 954 } 837 955 838 if (right < bounds.right) { 956 float last = 0.0f; 957 float lastTab = 0.0f; 958 if (fTabSide == B_TOP_BORDER || fTabSide == B_BOTTOM_BORDER) { 959 lastTab = TabFrame(tabCount - 1).right; 960 last = bounds.right; 961 tabsBounds.left = tabsBounds.right = lastTab; 962 borders = BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER; 963 } else if (fTabSide == B_LEFT_BORDER || fTabSide == B_RIGHT_BORDER) { 964 lastTab = TabFrame(tabCount - 1).bottom; 965 last = bounds.bottom; 966 tabsBounds.top = tabsBounds.bottom = lastTab; 967 borders = BControlLook::B_LEFT_BORDER | BControlLook::B_RIGHT_BORDER; 968 } 969 970 if (lastTab < last) { 839 971 // draw a 1px right border on the last tab 840 bounds = Bounds(); 841 bounds.left = bounds.right = right; 842 bounds.bottom = fTabHeight; 843 borders = BControlLook::B_TOP_BORDER; 844 be_control_look->DrawInactiveTab(this, bounds, bounds, base, 0, 845 BControlLook::B_TOP_BORDER | BControlLook::B_BOTTOM_BORDER); 972 be_control_look->DrawInactiveTab(this, tabsBounds, tabsBounds, base, 0, 973 borders, fTabSide); 846 974 } 847 975 848 976 return fSelection < CountTabs() ? TabFrame(fSelection) : BRect(); … … void 853 981 BTabView::DrawBox(BRect selectedTabRect) 854 982 { 855 983 BRect rect(Bounds()); 856 rect.top = fTabHeight; 984 uint32 bordersToDraw = BControlLook::B_ALL_BORDERS; 985 switch (fTabSide) { 986 case B_TOP_BORDER: 987 bordersToDraw &= ~BControlLook::B_TOP_BORDER; 988 rect.top = fTabHeight; 989 break; 990 case B_BOTTOM_BORDER: 991 bordersToDraw &= ~BControlLook::B_BOTTOM_BORDER; 992 rect.bottom -= fTabHeight; 993 break; 994 case B_LEFT_BORDER: 995 bordersToDraw &= ~BControlLook::B_LEFT_BORDER; 996 rect.left = fTabHeight; 997 break; 998 case B_RIGHT_BORDER: 999 bordersToDraw &= ~BControlLook::B_RIGHT_BORDER; 1000 rect.right -= fTabHeight; 1001 break; 1002 } 857 1003 858 1004 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); 859 if (fBorderStyle == B_FANCY_BORDER) { 860 be_control_look->DrawGroupFrame(this, rect, rect, base, 861 BControlLook::B_ALL_BORDERS & ~BControlLook::B_TOP_BORDER); 862 } else if (fBorderStyle == B_PLAIN_BORDER) { 1005 if (fBorderStyle == B_FANCY_BORDER) 1006 be_control_look->DrawGroupFrame(this, rect, rect, base, bordersToDraw); 1007 else if (fBorderStyle == B_PLAIN_BORDER) { 863 1008 be_control_look->DrawBorder(this, rect, rect, base, B_PLAIN_BORDER, 864 0, BControlLook::B_ALL_BORDERS & ~BControlLook::B_TOP_BORDER);1009 0, bordersToDraw); 865 1010 } else 866 1011 ; // B_NO_BORDER draws no box 867 1012 } … … BTabView::TabFrame(int32 index) const 876 1021 float width = 100.0f; 877 1022 float height = fTabHeight; 878 1023 float offset = BControlLook::ComposeSpacing(B_USE_WINDOW_SPACING); 1024 BRect bounds(Bounds()); 879 1025 880 1026 switch (fTabWidthSetting) { 881 1027 case B_WIDTH_FROM_LABEL: … … BTabView::TabFrame(int32 index) const 885 1031 x += StringWidth(TabAt(i)->Label()) + 20.0f; 886 1032 } 887 1033 888 return BRect(offset + x, 0.0f, 889 offset + x + StringWidth(TabAt(index)->Label()) + 20.0f, 890 height); 1034 switch (fTabSide) { 1035 case B_TOP_BORDER: 1036 return BRect(offset + x, 0.0f, 1037 offset + x + StringWidth(TabAt(index)->Label()) + 20.0f, 1038 height); 1039 case B_BOTTOM_BORDER: 1040 return BRect(offset + x, bounds.bottom - height, 1041 offset + x + StringWidth(TabAt(index)->Label()) + 20.0f, 1042 bounds.bottom); 1043 case B_LEFT_BORDER: 1044 return BRect(0.0f, offset + x, height, offset + x 1045 + StringWidth(TabAt(index)->Label()) + 20.0f); 1046 case B_RIGHT_BORDER: 1047 return BRect(bounds.right - height, offset + x, 1048 bounds.right, offset + x 1049 + StringWidth(TabAt(index)->Label()) + 20.0f); 1050 default: 1051 return BRect(); 1052 } 891 1053 } 892 1054 893 1055 case B_WIDTH_FROM_WIDEST: … … BTabView::TabFrame(int32 index) const 901 1063 902 1064 case B_WIDTH_AS_USUAL: 903 1065 default: 904 return BRect(offset + index * width, 0.0f, 905 offset + index * width + width, height); 1066 switch (fTabSide) { 1067 case B_TOP_BORDER: 1068 return BRect(offset + index * width, 0.0f, 1069 offset + index * width + width, height); 1070 case B_BOTTOM_BORDER: 1071 return BRect(offset + index * width, bounds.bottom - height, 1072 offset + index * width + width, bounds.bottom); 1073 case B_LEFT_BORDER: 1074 return BRect(0.0f, offset + index * width, height, 1075 offset + index * width + width); 1076 case B_RIGHT_BORDER: 1077 return BRect(bounds.right - height, offset + index * width, 1078 bounds.right, offset + index * width + width); 1079 default: 1080 return BRect(); 1081 } 906 1082 } 907 1083 } 908 1084 … … BTabView::Border() const 1153 1329 } 1154 1330 1155 1331 1332 void 1333 BTabView::SetTabSide(tab_side tabSide) 1334 { 1335 if (fTabSide == tabSide) 1336 return; 1337 1338 fTabSide = tabSide; 1339 _LayoutContainerView(Flags() & B_SUPPORTS_LAYOUT); 1340 } 1341 1342 1343 tab_side 1344 BTabView::TabSide() const 1345 { 1346 return fTabSide; 1347 } 1348 1349 1156 1350 BView* 1157 1351 BTabView::ContainerView() const 1158 1352 { … … BTabView::_InitObject(bool layouted, button_width width) 1188 1382 fFocus = -1; 1189 1383 fTabOffset = 0.0f; 1190 1384 fBorderStyle = B_FANCY_BORDER; 1385 fTabSide = B_TOP_BORDER; 1191 1386 1192 1387 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 1193 1388 SetLowUIColor(B_PANEL_BACKGROUND_COLOR); … … BTabView::_LayoutContainerView(bool layouted) 1292 1487 } 1293 1488 BGroupLayout* layout = dynamic_cast<BGroupLayout*>(GetLayout()); 1294 1489 if (layout != NULL) { 1295 layout->SetInsets(borderWidth, borderWidth + TabHeight() 1296 - topBorderOffset, borderWidth, borderWidth); 1490 float inset = borderWidth + TabHeight() - topBorderOffset; 1491 switch (fTabSide) { 1492 case B_TOP_BORDER: 1493 layout->SetInsets(borderWidth, inset, borderWidth, 1494 borderWidth); 1495 break; 1496 case B_BOTTOM_BORDER: 1497 layout->SetInsets(borderWidth, borderWidth, borderWidth, 1498 inset); 1499 break; 1500 case B_LEFT_BORDER: 1501 layout->SetInsets(inset, borderWidth, borderWidth, 1502 borderWidth); 1503 break; 1504 case B_RIGHT_BORDER: 1505 layout->SetInsets(borderWidth, borderWidth, inset, 1506 borderWidth); 1507 break; 1508 } 1297 1509 } 1298 1510 } else { 1299 1511 BRect bounds = Bounds(); 1300 1301 bounds.top += TabHeight(); 1512 switch (fTabSide) { 1513 case B_TOP_BORDER: 1514 bounds.top += TabHeight(); 1515 break; 1516 case B_BOTTOM_BORDER: 1517 bounds.bottom -= TabHeight(); 1518 break; 1519 case B_LEFT_BORDER: 1520 bounds.left += TabHeight(); 1521 break; 1522 case B_RIGHT_BORDER: 1523 bounds.right -= TabHeight(); 1524 break; 1525 } 1302 1526 bounds.InsetBy(borderWidth, borderWidth); 1303 1527 1304 1528 fContainerView->MoveTo(bounds.left, bounds.top); … … BTabView::_LayoutContainerView(bool layouted) 1310 1534 // #pragma mark - FBC and forbidden 1311 1535 1312 1536 1313 void BTabView::_ReservedTabView2() {}1314 void BTabView::_ReservedTabView3() {}1315 1537 void BTabView::_ReservedTabView4() {} 1316 1538 void BTabView::_ReservedTabView5() {} 1317 1539 void BTabView::_ReservedTabView6() {}