bool TabDecorator::_MoveTab(int32 from, int32 to, bool isMoving, BRegion* updateRegion) { Decorator::Tab* toTab = _TabAt(to); if (toTab == NULL) return false; if (from < to) { fOldMovingTab.OffsetBy(toTab->tabRect.Width(), 0); toTab->tabRect.OffsetBy(-fOldMovingTab.Width(), 0); } else { fOldMovingTab.OffsetBy(-toTab->tabRect.Width(), 0); toTab->tabRect.OffsetBy(fOldMovingTab.Width(), 0); } toTab->tabOffset = uint32(toTab->tabRect.left - fLeftBorder.left); _LayoutTabItems(toTab, toTab->tabRect); _CalculateTabsRegion(); if (updateRegion != NULL) updateRegion->Include(fTitleBarRect); return true; }
bool TabDecorator::SetRegionHighlight(Region region, uint8 highlight, BRegion* dirty, int32 tabIndex) { Decorator::Tab* tab = static_cast<Decorator::Tab*>(_TabAt(tabIndex)); if (tab != NULL) { tab->isHighlighted = highlight != 0; // Invalidate the bitmap caches for the close/zoom button, when the // highlight changes. switch (region) { case REGION_CLOSE_BUTTON: if (highlight != RegionHighlight(region)) memset(&tab->closeBitmaps, 0, sizeof(tab->closeBitmaps)); break; case REGION_ZOOM_BUTTON: if (highlight != RegionHighlight(region)) memset(&tab->zoomBitmaps, 0, sizeof(tab->zoomBitmaps)); break; default: break; } } return Decorator::SetRegionHighlight(region, highlight, dirty, tabIndex); }
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 != NULL && 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); else fController->SetToolTip("Double-click or middle-click to open new tab."); } }
void TabDecorator::_DistributeTabSize(float delta) { ASSERT(CountTabs() > 1); float maxTabSize = 0; float secMaxTabSize = 0; int32 nTabsWithMaxSize = 0; for (int32 i = 0; i < fTabList.CountItems(); i++) { Decorator::Tab* tab = fTabList.ItemAt(i); float tabWidth = tab->tabRect.Width(); if (int_equal(maxTabSize, tabWidth)) { nTabsWithMaxSize++; continue; } if (maxTabSize < tabWidth) { secMaxTabSize = maxTabSize; maxTabSize = tabWidth; nTabsWithMaxSize = 1; } else if (secMaxTabSize <= tabWidth) secMaxTabSize = tabWidth; } float minus = ceil(std::min(maxTabSize - secMaxTabSize, delta)); delta -= minus; minus /= nTabsWithMaxSize; Decorator::Tab* prevTab = NULL; for (int32 i = 0; i < fTabList.CountItems(); i++) { Decorator::Tab* tab = fTabList.ItemAt(i); if (int_equal(maxTabSize, tab->tabRect.Width())) tab->tabRect.right -= minus; if (prevTab) { tab->tabRect.OffsetBy(prevTab->tabRect.right - tab->tabRect.left, 0); } prevTab = tab; } if (delta > 0) { _DistributeTabSize(delta); return; } // done prevTab->tabRect.right = floor(fFrame.right + fBorderWidth); for (int32 i = 0; i < fTabList.CountItems(); i++) { Decorator::Tab* tab = _TabAt(i); tab->tabOffset = uint32(tab->tabRect.left - fLeftBorder.left); } }
float TabDecorator::_SingleTabOffsetAndSize(float& tabSize) { float maxLocation; if (fTopTab->look != kLeftTitledWindowLook) { tabSize = fRightBorder.right - fLeftBorder.left; } else { tabSize = fBottomBorder.bottom - fTopBorder.top; } Decorator::Tab* tab = _TabAt(0); maxLocation = tabSize - tab->maxTabSize; if (maxLocation < 0) maxLocation = 0; return floorf(tab->tabLocation * maxLocation); }
void TabDecorator::_ResizeBy(BPoint offset, BRegion* dirty) { STRACE(("TabDecorator: Resize By (%.1f, %.1f)\n", offset.x, offset.y)); // Move all internal rectangles the appropriate amount fFrame.right += offset.x; fFrame.bottom += offset.y; // Handle invalidation of resize rect if (dirty != NULL && !(fTopTab->flags & B_NOT_RESIZABLE)) { BRect realResizeRect; switch ((int)fTopTab->look) { case B_DOCUMENT_WINDOW_LOOK: realResizeRect = fResizeRect; // Resize rect at old location dirty->Include(realResizeRect); realResizeRect.OffsetBy(offset); // Resize rect at new location dirty->Include(realResizeRect); break; case B_TITLED_WINDOW_LOOK: case B_FLOATING_WINDOW_LOOK: case B_MODAL_WINDOW_LOOK: case kLeftTitledWindowLook: // The bottom border resize line realResizeRect.Set(fRightBorder.right - kBorderResizeLength, fBottomBorder.top, fRightBorder.right - kBorderResizeLength, fBottomBorder.bottom - 1); // Old location dirty->Include(realResizeRect); realResizeRect.OffsetBy(offset); // New location dirty->Include(realResizeRect); // The right border resize line realResizeRect.Set(fRightBorder.left, fBottomBorder.bottom - kBorderResizeLength, fRightBorder.right - 1, fBottomBorder.bottom - kBorderResizeLength); // Old location dirty->Include(realResizeRect); realResizeRect.OffsetBy(offset); // New location dirty->Include(realResizeRect); break; default: break; } } fResizeRect.OffsetBy(offset); fBorderRect.right += offset.x; fBorderRect.bottom += offset.y; fLeftBorder.bottom += offset.y; fTopBorder.right += offset.x; fRightBorder.OffsetBy(offset.x, 0.0); fRightBorder.bottom += offset.y; fBottomBorder.OffsetBy(0.0, offset.y); fBottomBorder.right += offset.x; if (dirty) { if (offset.x > 0.0) { BRect t(fRightBorder.left - offset.x, fTopBorder.top, fRightBorder.right, fTopBorder.bottom); dirty->Include(t); t.Set(fRightBorder.left - offset.x, fBottomBorder.top, fRightBorder.right, fBottomBorder.bottom); dirty->Include(t); dirty->Include(fRightBorder); } else if (offset.x < 0.0) { dirty->Include(BRect(fRightBorder.left, fTopBorder.top, fRightBorder.right, fBottomBorder.bottom)); } if (offset.y > 0.0) { BRect t(fLeftBorder.left, fLeftBorder.bottom - offset.y, fLeftBorder.right, fLeftBorder.bottom); dirty->Include(t); t.Set(fRightBorder.left, fRightBorder.bottom - offset.y, fRightBorder.right, fRightBorder.bottom); dirty->Include(t); dirty->Include(fBottomBorder); } else if (offset.y < 0.0) { dirty->Include(fBottomBorder); } } // resize tab and layout tab items if (fTitleBarRect.IsValid()) { if (fTabList.CountItems() > 1) { _DoTabLayout(); if (dirty != NULL) dirty->Include(fTitleBarRect); return; } Decorator::Tab* tab = _TabAt(0); BRect& tabRect = tab->tabRect; BRect oldTabRect(tabRect); float tabSize; float tabOffset = _SingleTabOffsetAndSize(tabSize); float delta = tabOffset - tab->tabOffset; tab->tabOffset = (uint32)tabOffset; if (fTopTab->look != kLeftTitledWindowLook) tabRect.OffsetBy(delta, 0.0); else tabRect.OffsetBy(0.0, delta); if (tabSize < tab->minTabSize) tabSize = tab->minTabSize; if (tabSize > tab->maxTabSize) tabSize = tab->maxTabSize; if (fTopTab->look != kLeftTitledWindowLook && tabSize != tabRect.Width()) { tabRect.right = tabRect.left + tabSize; } else if (fTopTab->look == kLeftTitledWindowLook && tabSize != tabRect.Height()) { tabRect.bottom = tabRect.top + tabSize; } if (oldTabRect != tabRect) { _LayoutTabItems(tab, tabRect); if (dirty) { // NOTE: the tab rect becoming smaller only would // handled be the Desktop anyways, so it is sufficient // to include it into the dirty region in it's // final state BRect redraw(tabRect); if (delta != 0.0) { redraw = redraw | oldTabRect; if (fTopTab->look != kLeftTitledWindowLook) redraw.bottom++; else redraw.right++; } dirty->Include(redraw); } } fTitleBarRect = tabRect; fTabsRegion = fTitleBarRect; } }
void TabDecorator::_DoTabLayout() { float tabOffset = 0; if (fTabList.CountItems() == 1) { float tabSize; tabOffset = _SingleTabOffsetAndSize(tabSize); } float sumTabWidth = 0; // calculate our tab rect for (int32 i = 0; i < fTabList.CountItems(); i++) { Decorator::Tab* tab = _TabAt(i); BRect& tabRect = tab->tabRect; // distance from one item of the tab bar to another. // In this case the text and close/zoom rects tab->textOffset = _DefaultTextOffset(); font_height fontHeight; fDrawState.Font().GetHeight(fontHeight); if (tab->look != kLeftTitledWindowLook) { tabRect.Set(fFrame.left - fBorderWidth, fFrame.top - fBorderWidth - ceilf(fontHeight.ascent + fontHeight.descent + 7.0), ((fFrame.right - fFrame.left) < 35.0 ? fFrame.left + 35.0 : fFrame.right) + fBorderWidth, fFrame.top - fBorderWidth); } else { tabRect.Set(fFrame.left - fBorderWidth - ceilf(fontHeight.ascent + fontHeight.descent + 5.0), fFrame.top - fBorderWidth, fFrame.left - fBorderWidth, fFrame.bottom + fBorderWidth); } // format tab rect for a floating window - make the rect smaller if (tab->look == B_FLOATING_WINDOW_LOOK) { tabRect.InsetBy(0, 2); tabRect.OffsetBy(0, 2); } float offset; float size; float inset; _GetButtonSizeAndOffset(tabRect, &offset, &size, &inset); // tab->minTabSize contains just the room for the buttons tab->minTabSize = inset * 2 + tab->textOffset; if ((tab->flags & B_NOT_CLOSABLE) == 0) tab->minTabSize += offset + size; if ((tab->flags & B_NOT_ZOOMABLE) == 0) tab->minTabSize += offset + size; // tab->maxTabSize contains tab->minTabSize + the width required for the // title tab->maxTabSize = fDrawingEngine ? ceilf(fDrawingEngine->StringWidth(Title(tab), strlen(Title(tab)), fDrawState.Font())) : 0.0; if (tab->maxTabSize > 0.0) tab->maxTabSize += tab->textOffset; tab->maxTabSize += tab->minTabSize; float tabSize = (tab->look != kLeftTitledWindowLook ? fFrame.Width() : fFrame.Height()) + fBorderWidth * 2; if (tabSize < tab->minTabSize) tabSize = tab->minTabSize; if (tabSize > tab->maxTabSize) tabSize = tab->maxTabSize; // layout buttons and truncate text if (tab->look != kLeftTitledWindowLook) tabRect.right = tabRect.left + tabSize; else tabRect.bottom = tabRect.top + tabSize; // make sure fTabOffset is within limits and apply it to // the tabRect tab->tabOffset = (uint32)tabOffset; if (tab->tabLocation != 0.0 && fTabList.CountItems() == 1 && tab->tabOffset > (fRightBorder.right - fLeftBorder.left - tabRect.Width())) { tab->tabOffset = uint32(fRightBorder.right - fLeftBorder.left - tabRect.Width()); } tabRect.OffsetBy(tab->tabOffset, 0); tabOffset += tabRect.Width(); sumTabWidth += tabRect.Width(); } float windowWidth = fFrame.Width() + 2 * fBorderWidth; if (CountTabs() > 1 && sumTabWidth > windowWidth) _DistributeTabSize(sumTabWidth - windowWidth); // finally, layout the buttons and text within the tab rect for (int32 i = 0; i < fTabList.CountItems(); i++) { Decorator::Tab* tab = fTabList.ItemAt(i); if (i == 0) fTitleBarRect = tab->tabRect; else fTitleBarRect = fTitleBarRect | tab->tabRect; _LayoutTabItems(tab, tab->tabRect); } fTabsRegion = fTitleBarRect; }