diff --git a/build/jam/packages/Haiku b/build/jam/packages/Haiku index 655344d530..fdc6a61422 100644 --- a/build/jam/packages/Haiku +++ b/build/jam/packages/Haiku @@ -266,10 +266,6 @@ AddFilesToPackage add-ons disk_systems # Kernel bluetooth stack AddFilesToPackage add-ons kernel bluetooth : $(SYSTEM_BT_STACK) ; -# decorators -AddFilesToPackage add-ons decorators : BeDecorator ; - # MacDecorator WinDecorator - # the MIME DB CopyDirectoryToPackage data : mime_db : : : isTarget ; diff --git a/build/jam/packages/HaikuExtras b/build/jam/packages/HaikuExtras index 0d5ccd257d..e5439e185c 100644 --- a/build/jam/packages/HaikuExtras +++ b/build/jam/packages/HaikuExtras @@ -3,11 +3,22 @@ local architecture = $(HAIKU_PACKAGING_ARCHS[1]) ; local extrasPackage = haiku_extras.hpkg ; HaikuPackage $(extrasPackage) ; +## Driver Oddities + # kernel modules AddFilesToPackage add-ons kernel partitioning_systems : amiga_rdb@!m68k apple@!ppc sun@!sparc ; -AddFilesToPackage add-ons control_look : BeControlLook ; + +## Visual Oddities + +# MacDecorator WinDecorator need improved stack and tile support + +# Control Looks +AddFilesToPackage add-ons control_look : BeControlLook FlatControlLook ; + +# Decorators +AddFilesToPackage add-ons decorators : BeDecorator FlatDecorator ; + BuildHaikuPackage $(extrasPackage) : haiku_extras ; - diff --git a/src/add-ons/control_look/FlatControlLook/FlatControlLook.cpp b/src/add-ons/control_look/FlatControlLook/FlatControlLook.cpp new file mode 100644 index 0000000000..cbfca0e2f2 --- /dev/null +++ b/src/add-ons/control_look/FlatControlLook/FlatControlLook.cpp @@ -0,0 +1,2274 @@ +/* + * Copyright 2021 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus, superstippi@gmx.de + * John Scipione, jscipione@gmail.com + * Nahuel Tello, ntello@unarix.com.ar + */ + + +/*! FlatControlLook flat Haiku */ + + +#include "FlatControlLook.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +namespace BPrivate { + +static const float kEdgeBevelLightTint = 1.0; +static const float kEdgeBevelShadowTint = 1.0; +static const float kHoverTintFactor = 0.55; + +static const float kButtonPopUpIndicatorWidth = 11; + + +FlatControlLook::FlatControlLook(): HaikuControlLook() +{ +} + + +FlatControlLook::~FlatControlLook() +{ +} + + +// #pragma mark - + + +void +HaikuControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, const rgb_color& background, uint32 flags, + uint32 borders) +{ + _DrawButtonFrame(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f, base, + background, 1.0, 1.0, flags, borders); +} + + +void +HaikuControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect, + float radius, const rgb_color& base, const rgb_color& background, uint32 flags, + uint32 borders) +{ + _DrawButtonFrame(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f, + base, background, 1.0, 1.0, flags, borders); +} + + +void +HaikuControlLook::DrawButtonFrame(BView* view, BRect& rect, + const BRect& updateRect, float leftTopRadius, float rightTopRadius, + float leftBottomRadius, float rightBottomRadius, const rgb_color& base, + const rgb_color& background, uint32 flags, + uint32 borders) +{ + _DrawButtonFrame(view, rect, updateRect, 1.5f, 1.5f, + 1.5f, 1.5f, base, background, + 1.0, 1.0, flags, borders); +} + + +void +FlatControlLook::DrawButtonBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders, orientation orientation) +{ + _DrawButtonBackground(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f, + base, false, flags, borders, orientation); +} + + +void +FlatControlLook::DrawButtonBackground(BView* view, BRect& rect, + const BRect& updateRect, float radius, const rgb_color& base, uint32 flags, + uint32 borders, orientation orientation) +{ + _DrawButtonBackground(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f, + base, false, flags, borders, orientation); +} + + +void +FlatControlLook::DrawButtonBackground(BView* view, BRect& rect, + const BRect& updateRect, float leftTopRadius, float rightTopRadius, + float leftBottomRadius, float rightBottomRadius, const rgb_color& base, + uint32 flags, uint32 borders, orientation orientation) +{ + _DrawButtonBackground(view, rect, updateRect, 1.5f, + 1.5f, 1.5f, 1.5f, base, false, flags, + borders, orientation); +} + + +void +FlatControlLook::DrawMenuBarBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + // the surface edges + + // colors + float topTint = 1.0; + float bottomTint = 1.16; + + rgb_color customColor = base; + bool isEnabled = (flags & B_ACTIVATED) != 0; + + if (isEnabled) { + customColor = tint_color(ui_color(B_WINDOW_TAB_COLOR), 1.0); + rgb_color bevelColor1 = tint_color(customColor, 1.0); + rgb_color bevelColor2 = tint_color(customColor, 1.0); + + topTint = 1.0; + bottomTint = 1.0; + + _DrawFrame(view, rect, + bevelColor1, bevelColor1, + bevelColor2, bevelColor2, + borders & B_TOP_BORDER); + } else { + rgb_color cornerColor = tint_color(customColor, 1.0); + rgb_color bevelColorTop = tint_color(customColor, 1.0); + rgb_color bevelColorLeft = tint_color(customColor, 1.0); + rgb_color bevelColorRightBottom = tint_color(customColor, 1.0); + + topTint = 1.0; + bottomTint = 1.0; + + _DrawFrame(view, rect, + bevelColorLeft, bevelColorTop, + bevelColorRightBottom, bevelColorRightBottom, + cornerColor, cornerColor, + borders); + } + + // draw surface top + _FillGradient(view, rect, customColor, topTint, bottomTint); +} + + +void +FlatControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, + const rgb_color& background, uint32 flags, uint32 borders) +{ + _DrawButtonFrame(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f, base, + background, 1.0, 1.0, flags, borders); +} + + +void +FlatControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, + const BRect& updateRect, float radius, const rgb_color& base, + const rgb_color& background, uint32 flags, uint32 borders) +{ + _DrawButtonFrame(view, rect, updateRect, radius, radius, 1.5f, 1.5f, + base, background, 1.0, 1.0, flags, borders); +} + + +void +FlatControlLook::DrawMenuFieldFrame(BView* view, BRect& rect, + const BRect& updateRect, float leftTopRadius, + float rightTopRadius, float leftBottomRadius, + float rightBottomRadius, const rgb_color& base, + const rgb_color& background, uint32 flags, uint32 borders) +{ + _DrawButtonFrame(view, rect, updateRect, leftTopRadius, rightTopRadius, + 1.5f, 1.5f, base, background, 1.0, 1.0, + flags, borders); +} + + +void +FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, bool popupIndicator, + uint32 flags) +{ + _DrawMenuFieldBackgroundOutside(view, rect, updateRect, + 1.5f, 1.5f, 1.5f, 1.5f, base, popupIndicator, flags); +} + + +void +FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders) +{ + _DrawMenuFieldBackgroundInside(view, rect, updateRect, + 1.5f, 1.5f, 1.5f, 1.5f, base, flags, borders); +} + + +void +FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, + const BRect& updateRect, float radius, const rgb_color& base, + bool popupIndicator, uint32 flags) +{ + _DrawMenuFieldBackgroundOutside(view, rect, updateRect, radius, radius, + radius, radius, base, popupIndicator, flags); +} + + +void +FlatControlLook::DrawMenuFieldBackground(BView* view, BRect& rect, + const BRect& updateRect, float leftTopRadius, float rightTopRadius, + float leftBottomRadius, float rightBottomRadius, const rgb_color& base, + bool popupIndicator, uint32 flags) +{ + _DrawMenuFieldBackgroundOutside(view, rect, updateRect, leftTopRadius, + rightTopRadius, leftBottomRadius, rightBottomRadius, base, + popupIndicator, flags); +} + + +void +HaikuControlLook::DrawMenuBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + // surface top color + rgb_color background = tint_color(base, 0.8); + + // inner bevel colors + rgb_color bevelColor; + + + if ((flags & B_DISABLED) != 0) { + bevelColor = tint_color(background, 1.03); + } else { + bevelColor = tint_color(background, 0.5); + } + + // draw inner bevel + _DrawFrame(view, rect, + bevelColor, bevelColor, + bevelColor, bevelColor, + borders); + + // draw surface top + view->SetHighColor(background); + view->FillRect(rect); +} + + +void +FlatControlLook::DrawMenuItemBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + // surface edges + float topTint; + float bottomTint; + rgb_color selectedColor = base; + + if ((flags & B_ACTIVATED) != 0) { + topTint = 0.94; + bottomTint = 1.1; + } else if ((flags & B_DISABLED) != 0) { + topTint = 1.0; + bottomTint = 1.0; + } else { + topTint = 0.95; + bottomTint = 1.1; + } + + //rgb_color bevelLightColor = tint_color(selectedColor, topTint); + rgb_color bevelShadowColor = tint_color(selectedColor, bottomTint); + + // draw surface edges + _DrawFrame(view, rect, + bevelShadowColor, bevelShadowColor, + bevelShadowColor, bevelShadowColor, + borders); + + // draw surface top + view->SetLowColor(selectedColor); + _FillGradient(view, rect, selectedColor, topTint, bottomTint); +} + + +void +HaikuControlLook::DrawScrollBarBorder(BView* view, BRect rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + orientation orientation) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + view->PushState(); + + // set clipping constraints to updateRect + BRegion clipping(updateRect); + view->ConstrainClippingRegion(&clipping); + + bool isEnabled = (flags & B_DISABLED) == 0; + bool isFocused = (flags & B_FOCUSED) != 0; + + view->SetHighColor(tint_color(base, 1.2)); + + // stroke a line around the entire scrollbar + // take care of border highlighting, scroll target is focus view + if (isEnabled && isFocused) { + rgb_color borderColor = tint_color(base, 1.2); + rgb_color highlightColor = tint_color(base, 1.2); + + view->BeginLineArray(4); + + view->AddLine(BPoint(rect.left + 1, rect.bottom), + BPoint(rect.right, rect.bottom), borderColor); + view->AddLine(BPoint(rect.right, rect.top + 1), + BPoint(rect.right, rect.bottom - 1), borderColor); + + if (orientation == B_HORIZONTAL) { + view->AddLine(BPoint(rect.left, rect.top + 1), + BPoint(rect.left, rect.bottom), borderColor); + } else { + view->AddLine(BPoint(rect.left, rect.top), + BPoint(rect.left, rect.bottom), highlightColor); + } + + if (orientation == B_HORIZONTAL) { + view->AddLine(BPoint(rect.left, rect.top), + BPoint(rect.right, rect.top), highlightColor); + } else { + view->AddLine(BPoint(rect.left + 1, rect.top), + BPoint(rect.right, rect.top), borderColor); + } + + view->EndLineArray(); + } else + view->StrokeRect(rect); + + view->PopState(); +} + + +void +HaikuControlLook::DrawScrollBarButton(BView* view, BRect rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + int32 direction, orientation orientation, bool down) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + bool dark = (base.red + base.green + base.blue <= 128 * 3); + rgb_color arrowColor; + + bool isEnabled = (flags & B_DISABLED) == 0; + + if (isEnabled) { + arrowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 0.6); + // if the base color is too dark, then lets make it lighter + if (dark) { + arrowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 1.3);; + } + } else { + arrowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 0.4); + // if the base color is too dark, then lets make it lighter + if (dark) { + arrowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 1.5);; + } + } + + // clip to button + BRegion buttonRegion(rect); + view->ConstrainClippingRegion(&buttonRegion); + + flags &= ~B_FLAT; + + DrawScrollBarBackground(view, rect, updateRect, base, flags, orientation); + rect.InsetBy(1, 1); + DrawArrowShape(view, rect, updateRect, arrowColor, direction, flags, 1.0f); + + // revert clipping constraints + BRegion clipping(updateRect); + view->ConstrainClippingRegion(&clipping); +} + + +void +HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect1, + BRect& rect2, const BRect& updateRect, const rgb_color& base, uint32 flags, + orientation orientation) +{ + DrawScrollBarBackground(view, rect1, updateRect, base, flags, orientation); + DrawScrollBarBackground(view, rect2, updateRect, base, flags, orientation); +} + + +void +HaikuControlLook::DrawScrollBarBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + orientation orientation) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + view->PushState(); + + // set clipping constraints to updateRect + BRegion clipping(updateRect); + view->ConstrainClippingRegion(&clipping); + + bool isEnabled = (flags & B_DISABLED) == 0; + + // fill background, we'll draw arrows and thumb on top + view->SetDrawingMode(B_OP_COPY); + + float gradient1Tint; + float gradient2Tint; + + if (isEnabled) { + gradient1Tint = 1.08; + gradient2Tint = 0.99; + } else { + gradient1Tint = 1.08; + gradient2Tint = 0.99; + } + + if (orientation == B_HORIZONTAL) { + // dark vertical line on left edge + // fill + if (rect.Width() >= 0) { + _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, + orientation); + } + } else { + // dark vertical line on top edge + // fill + if (rect.Height() >= 0) { + _FillGradient(view, rect, base, gradient1Tint, gradient2Tint, + orientation); + } + } + + view->PopState(); +} + + +void +FlatControlLook::DrawScrollBarThumb(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + orientation orientation, uint32 knobStyle) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + view->PushState(); + + // set clipping constraints to updateRect + BRegion clipping(updateRect); + view->ConstrainClippingRegion(&clipping); + + // flags + bool isEnabled = (flags & B_DISABLED) == 0; + + // colors + rgb_color thumbColor = ui_color(B_SCROLL_BAR_THUMB_COLOR); + rgb_color base_panel = ui_color(B_PANEL_BACKGROUND_COLOR); + + rgb_color light, dark, dark1, dark2; + light = tint_color(base_panel, B_DARKEN_1_TINT); + dark = tint_color(base_panel, B_DARKEN_1_TINT); + dark1 = tint_color(base_panel, B_DARKEN_1_TINT); + dark2 = tint_color(base_panel, B_DARKEN_1_TINT); + + // draw thumb over background + view->SetDrawingMode(B_OP_OVER); + view->SetHighColor(dark1); + + // draw scroll thumb + if (isEnabled) { + // fill the clickable surface of the thumb + // set clipping constraints to updateRect + BRegion clipping(updateRect); + view->ConstrainClippingRegion(&clipping); + DrawScrollBarBackground(view, rect, updateRect, base_panel, flags, orientation); + rect.InsetBy(3, 3); + view->SetHighColor(base_panel); + view->FillRect(rect); + + _DrawNonFlatButtonBackground(view, rect, updateRect, clipping, 4.0f, 4.0f, 4.0f, 4.0f, thumbColor, false, flags, B_ALL_BORDERS, orientation); + + } else { + DrawScrollBarBackground(view, rect, updateRect, base_panel, flags, orientation); + } + + knobStyle = B_KNOB_LINES; //Hard set of the knobstyle + + // draw knob style + if (knobStyle != B_KNOB_NONE && isEnabled) { + rgb_color knobLight = isEnabled + ? tint_color(thumbColor, 0.85) + : tint_color(base_panel, 1.05); + rgb_color knobDark = isEnabled + ? tint_color(thumbColor, 1.35) + : tint_color(base_panel, 1.05); + + if (knobStyle == B_KNOB_DOTS) { + // draw dots on the scroll bar thumb + float hcenter = rect.left + rect.Width() / 2; + float vmiddle = rect.top + rect.Height() / 2; + BRect knob(hcenter, vmiddle, hcenter, vmiddle); + + if (orientation == B_HORIZONTAL) { + view->SetHighColor(knobDark); + view->FillRect(knob); + view->SetHighColor(knobLight); + view->FillRect(knob.OffsetByCopy(1, 1)); + + float spacer = rect.Height(); + + if (rect.left + 3 < hcenter - spacer) { + view->SetHighColor(knobDark); + view->FillRect(knob.OffsetByCopy(-spacer, 0)); + view->SetHighColor(knobLight); + view->FillRect(knob.OffsetByCopy(-spacer + 1, 1)); + } + + if (rect.right - 3 > hcenter + spacer) { + view->SetHighColor(knobDark); + view->FillRect(knob.OffsetByCopy(spacer, 0)); + view->SetHighColor(knobLight); + view->FillRect(knob.OffsetByCopy(spacer + 1, 1)); + } + } else { + // B_VERTICAL + view->SetHighColor(knobDark); + view->FillRect(knob); + view->SetHighColor(knobLight); + view->FillRect(knob.OffsetByCopy(1, 1)); + + float spacer = rect.Width(); + + if (rect.top + 3 < vmiddle - spacer) { + view->SetHighColor(knobDark); + view->FillRect(knob.OffsetByCopy(0, -spacer)); + view->SetHighColor(knobLight); + view->FillRect(knob.OffsetByCopy(1, -spacer + 1)); + } + + if (rect.bottom - 3 > vmiddle + spacer) { + view->SetHighColor(knobDark); + view->FillRect(knob.OffsetByCopy(0, spacer)); + view->SetHighColor(knobLight); + view->FillRect(knob.OffsetByCopy(1, spacer + 1)); + } + } + } else if (knobStyle == B_KNOB_LINES && isEnabled) { + // draw lines on the scroll bar thumb + if (orientation == B_HORIZONTAL) { + float middle = rect.Width() / 2; + + view->BeginLineArray(6); + view->AddLine( + BPoint(rect.left + middle - 3, rect.top + 2), + BPoint(rect.left + middle - 3, rect.bottom - 2), + knobDark); + view->AddLine( + BPoint(rect.left + middle, rect.top + 2), + BPoint(rect.left + middle, rect.bottom - 2), + knobDark); + view->AddLine( + BPoint(rect.left + middle + 3, rect.top + 2), + BPoint(rect.left + middle + 3, rect.bottom - 2), + knobDark); + view->AddLine( + BPoint(rect.left + middle - 2, rect.top + 2), + BPoint(rect.left + middle - 2, rect.bottom - 2), + knobLight); + view->AddLine( + BPoint(rect.left + middle + 1, rect.top + 2), + BPoint(rect.left + middle + 1, rect.bottom - 2), + knobLight); + view->AddLine( + BPoint(rect.left + middle + 4, rect.top + 2), + BPoint(rect.left + middle + 4, rect.bottom - 2), + knobLight); + view->EndLineArray(); + } else { + // B_VERTICAL + float middle = rect.Height() / 2; + + view->BeginLineArray(6); + view->AddLine( + BPoint(rect.left + 2, rect.top + middle - 3), + BPoint(rect.right - 2, rect.top + middle - 3), + knobDark); + view->AddLine( + BPoint(rect.left + 2, rect.top + middle), + BPoint(rect.right - 2, rect.top + middle), + knobDark); + view->AddLine( + BPoint(rect.left + 2, rect.top + middle + 3), + BPoint(rect.right - 2, rect.top + middle + 3), + knobDark); + view->AddLine( + BPoint(rect.left + 2, rect.top + middle - 2), + BPoint(rect.right - 2, rect.top + middle - 2), + knobLight); + view->AddLine( + BPoint(rect.left + 2, rect.top + middle + 1), + BPoint(rect.right - 2, rect.top + middle + 1), + knobLight); + view->AddLine( + BPoint(rect.left + 2, rect.top + middle + 4), + BPoint(rect.right - 2, rect.top + middle + 4), + knobLight); + view->EndLineArray(); + } + } + } + + view->PopState(); +} + + +void +HaikuControlLook::DrawScrollViewFrame(BView* view, BRect& rect, + const BRect& updateRect, BRect verticalScrollBarFrame, + BRect horizontalScrollBarFrame, const rgb_color& base, + border_style borderStyle, uint32 flags, uint32 _borders) +{ + // calculate scroll corner rect before messing with the "rect" + BRect scrollCornerFillRect(rect.right, rect.bottom, + rect.right, rect.bottom); + + if (horizontalScrollBarFrame.IsValid()) + scrollCornerFillRect.left = horizontalScrollBarFrame.right + 1; + + if (verticalScrollBarFrame.IsValid()) + scrollCornerFillRect.top = verticalScrollBarFrame.bottom + 1; + + if (borderStyle == B_NO_BORDER) { + if (scrollCornerFillRect.IsValid()) { + view->SetHighColor(base); + view->FillRect(scrollCornerFillRect); + } + return; + } + + bool excludeScrollCorner = borderStyle == B_FANCY_BORDER + && horizontalScrollBarFrame.IsValid() + && verticalScrollBarFrame.IsValid(); + + uint32 borders = _borders; + if (excludeScrollCorner) { + rect.bottom = horizontalScrollBarFrame.top; + rect.right = verticalScrollBarFrame.left; + borders &= ~(B_RIGHT_BORDER | B_BOTTOM_BORDER); + } + + rgb_color scrollbarFrameColor = tint_color(base, 1.2); + + if (borderStyle == B_FANCY_BORDER) + _DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders); + + if ((flags & B_FOCUSED) != 0) { + _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor, + scrollbarFrameColor, scrollbarFrameColor, borders); + } else { + _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor, + scrollbarFrameColor, scrollbarFrameColor, borders); + } + + if (excludeScrollCorner) { + horizontalScrollBarFrame.InsetBy(-1, -1); + + // do not overdraw the top edge + horizontalScrollBarFrame.top += 2; + borders = _borders; + borders &= ~B_TOP_BORDER; + _DrawOuterResessedFrame(view, horizontalScrollBarFrame, base, + 1.0, 1.0, flags, borders); + _DrawFrame(view, horizontalScrollBarFrame, scrollbarFrameColor, + scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor, + borders); + + verticalScrollBarFrame.InsetBy(-1, -1); + + // do not overdraw the left edge + verticalScrollBarFrame.left += 2; + borders = _borders; + borders &= ~B_LEFT_BORDER; + _DrawOuterResessedFrame(view, verticalScrollBarFrame, base, + 1.0, 1.0, flags, borders); + _DrawFrame(view, verticalScrollBarFrame, scrollbarFrameColor, + scrollbarFrameColor, scrollbarFrameColor, scrollbarFrameColor, + borders); + + // exclude recessed frame + scrollCornerFillRect.top++; + scrollCornerFillRect.left++; + } + + if (scrollCornerFillRect.IsValid()) { + view->SetHighColor(base); + view->FillRect(scrollCornerFillRect); + } +} + + +rgb_color +HaikuControlLook::SliderBarColor(const rgb_color& base) +{ + rgb_color customColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 1.05); + // if the color BACKGROUND used is too dark, then make it lighter using the + // same as B_CONTROL_TEXT_COLOR + if (base.red + base.green + base.blue <= 128 * 3) { + customColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 0.95); + } + + return customColor; +} + + +void +HaikuControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect, + const rgb_color& base, rgb_color leftFillColor, rgb_color rightFillColor, + float sliderScale, uint32 flags, orientation orientation) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + // save the clipping constraints of the view + view->PushState(); + + // separate the bar in two sides + float sliderPosition; + BRect leftBarSide = rect; + BRect rightBarSide = rect; + + if (orientation == B_HORIZONTAL) { + sliderPosition = floorf(rect.left + 2 + (rect.Width() - 2) + * sliderScale); + leftBarSide.right = sliderPosition - 1; + rightBarSide.left = sliderPosition; + } else { + // NOTE: position is reverse of coords + sliderPosition = floorf(rect.top + 2 + (rect.Height() - 2) + * (1.0 - sliderScale)); + leftBarSide.top = sliderPosition; + rightBarSide.bottom = sliderPosition - 1; + } + + // fill the background for the corners, exclude the middle bar for now + BRegion region(rect); + region.Exclude(rightBarSide); + view->ConstrainClippingRegion(®ion); + + view->PushState(); + + DrawSliderBar(view, rect, updateRect, base, leftFillColor, flags, + orientation); + + view->PopState(); + + region.Set(rect); + region.Exclude(leftBarSide); + view->ConstrainClippingRegion(®ion); + + view->PushState(); + + DrawSliderBar(view, rect, updateRect, base, rightFillColor, flags, + orientation); + + view->PopState(); + + // restore the clipping constraints of the view + view->PopState(); +} + + +void +HaikuControlLook::DrawSliderBar(BView* view, BRect rect, const BRect& updateRect, + const rgb_color& base, rgb_color fillColor, uint32 flags, + orientation orientation) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + // separate the rect into corners + BRect leftCorner(rect); + BRect rightCorner(rect); + BRect barRect(rect); + + if (orientation == B_HORIZONTAL) { + leftCorner.right = leftCorner.left + leftCorner.Height(); + rightCorner.left = rightCorner.right - rightCorner.Height(); + barRect.left += ceilf(barRect.Height() / 2); + barRect.right -= ceilf(barRect.Height() / 2); + } else { + leftCorner.bottom = leftCorner.top + leftCorner.Width(); + rightCorner.top = rightCorner.bottom - rightCorner.Width(); + barRect.top += ceilf(barRect.Width() / 2); + barRect.bottom -= ceilf(barRect.Width() / 2); + } + + // fill the background for the corners, exclude the middle bar for now + BRegion region(rect); + region.Exclude(barRect); + view->ConstrainClippingRegion(®ion); + + if ((flags & B_BLEND_FRAME) == 0) { + view->SetHighColor(base); + view->FillRect(rect); + } + + // figure out the tints to be used + float edgeLightTint; + float edgeShadowTint; + float frameLightTint; + float frameShadowTint; + float fillLightTint; + float fillShadowTint; + uint8 edgeLightAlpha; + uint8 edgeShadowAlpha; + uint8 frameLightAlpha; + uint8 frameShadowAlpha; + + if ((flags & B_DISABLED) != 0) { + edgeLightTint = 1.0; + edgeShadowTint = 1.0; + frameLightTint = 1.05; + frameShadowTint = 1.05; + fillLightTint = 0.8; + fillShadowTint = 0.8; + edgeLightAlpha = 12; + edgeShadowAlpha = 12; + frameLightAlpha = 40; + frameShadowAlpha = 45; + + fillColor.red = uint8(fillColor.red * 0.4 + base.red * 0.6); + fillColor.green = uint8(fillColor.green * 0.4 + base.green * 0.6); + fillColor.blue = uint8(fillColor.blue * 0.4 + base.blue * 0.6); + } else { + edgeLightTint = 1.0; + edgeShadowTint = 1.0; + frameLightTint = 1.20; + frameShadowTint = 1.20; + fillLightTint = 0.9; + fillShadowTint = 0.9; + edgeLightAlpha = 15; + edgeShadowAlpha = 15; + frameLightAlpha = 102; + frameShadowAlpha = 117; + } + + rgb_color edgeLightColor; + rgb_color edgeShadowColor; + rgb_color frameLightColor; + rgb_color frameShadowColor; + rgb_color fillLightColor = tint_color(fillColor, fillLightTint); + rgb_color fillShadowColor = tint_color(fillColor, fillShadowTint); + + drawing_mode oldMode = view->DrawingMode(); + + if ((flags & B_BLEND_FRAME) != 0) { + edgeLightColor = (rgb_color){ 255, 255, 255, edgeLightAlpha }; + edgeShadowColor = (rgb_color){ 0, 0, 0, edgeShadowAlpha }; + frameLightColor = (rgb_color){ 0, 0, 0, frameLightAlpha }; + frameShadowColor = (rgb_color){ 0, 0, 0, frameShadowAlpha }; + + view->SetDrawingMode(B_OP_ALPHA); + } else { + edgeLightColor = tint_color(base, edgeLightTint); + edgeShadowColor = tint_color(base, edgeShadowTint); + frameLightColor = tint_color(fillColor, frameLightTint); + frameShadowColor = tint_color(fillColor, frameShadowTint); + } + + if (orientation == B_HORIZONTAL) { + _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor, + edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, + fillShadowColor, 1.0, 1.0, 0.0, -1.0, orientation); + + _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor, + edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, + fillShadowColor, 0.0, 1.0, -1.0, -1.0, orientation); + } else { + _DrawRoundBarCorner(view, leftCorner, updateRect, edgeLightColor, + edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, + fillShadowColor, 1.0, 1.0, -1.0, 0.0, orientation); + + _DrawRoundBarCorner(view, rightCorner, updateRect, edgeLightColor, + edgeShadowColor, frameLightColor, frameShadowColor, fillLightColor, + fillShadowColor, 1.0, 0.0, -1.0, -1.0, orientation); + } + + view->ConstrainClippingRegion(NULL); + + view->BeginLineArray(4); + if (orientation == B_HORIZONTAL) { + view->AddLine(barRect.LeftTop(), barRect.RightTop(), + edgeShadowColor); + view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), + edgeLightColor); + barRect.InsetBy(0, 1); + view->AddLine(barRect.LeftTop(), barRect.RightTop(), + frameShadowColor); + view->AddLine(barRect.LeftBottom(), barRect.RightBottom(), + frameLightColor); + barRect.InsetBy(0, 1); + } else { + view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), + edgeShadowColor); + view->AddLine(barRect.RightTop(), barRect.RightBottom(), + edgeLightColor); + barRect.InsetBy(1, 0); + view->AddLine(barRect.LeftTop(), barRect.LeftBottom(), + frameShadowColor); + view->AddLine(barRect.RightTop(), barRect.RightBottom(), + frameLightColor); + barRect.InsetBy(1, 0); + } + view->EndLineArray(); + + view->SetDrawingMode(oldMode); + + _FillGradient(view, barRect, fillColor, fillShadowTint, fillLightTint, + orientation); +} + + +void +HaikuControlLook::DrawSliderThumb(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, uint32 flags, orientation orientation) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + rgb_color thumbColor = tint_color(ui_color(B_SCROLL_BAR_THUMB_COLOR), 1.0); + + // figure out frame color + rgb_color frameLightColor; + rgb_color frameShadowColor; + rgb_color shadowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 0.5); + + //if the color BACKGROUND used is too dark, then make it lighter using the same as B_CONTROL_TEXT_COLOR + if (base.red + base.green + base.blue <= 128 * 3) { + shadowColor = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 1.55); + } + + if ((flags & B_FOCUSED) != 0) { + // focused + frameLightColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + frameShadowColor = frameLightColor; + } else { + // figure out the tints to be used + float frameLightTint; + float frameShadowTint; + + if ((flags & B_DISABLED) != 0) { + frameLightTint = 1.30; + frameShadowTint = 1.35; + shadowColor.alpha = 30; + } else { + frameLightTint = 1.6; + frameShadowTint = 1.65; + } + + frameLightColor = tint_color(base, frameLightTint); + frameShadowColor = tint_color(base, frameShadowTint); + } + + BRect originalRect(rect); + rect.right--; + rect.bottom--; + + _DrawFrame(view, rect, shadowColor, shadowColor, shadowColor, shadowColor); + + flags &= ~B_ACTIVATED; + flags &= ~B_FLAT; + DrawScrollBarBackground(view, rect, updateRect, base, flags, orientation); + + // thumb edge + if (orientation == B_HORIZONTAL) { + rect.InsetBy(0, floorf(rect.Height() / 4)); + rect.left = floorf((rect.left + rect.right) / 2); + rect.right = rect.left; + shadowColor = tint_color(thumbColor, 1.5); + view->SetHighColor(shadowColor); + view->StrokeLine(rect.LeftTop(), rect.LeftBottom()); + rgb_color lightColor = tint_color(thumbColor, 1.0); + view->SetHighColor(lightColor); + view->StrokeLine(rect.RightTop(), rect.RightBottom()); + } else { + rect.InsetBy(floorf(rect.Width() / 4), 0); + rect.top = floorf((rect.top + rect.bottom) / 2); + rect.bottom = rect.top + 1; + shadowColor = tint_color(thumbColor, 1.5); + view->SetHighColor(shadowColor); + view->StrokeLine(rect.LeftTop(), rect.RightTop()); + rgb_color lightColor = tint_color(thumbColor, 1.0); + view->SetHighColor(lightColor); + view->StrokeLine(rect.LeftBottom(), rect.RightBottom()); + } + + view->SetDrawingMode(B_OP_COPY); +} + + +void +HaikuControlLook::DrawActiveTab(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders, uint32 side, int32, int32, int32, int32) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + // Snap the rectangle to pixels to avoid rounding errors. + rect.left = floorf(rect.left); + rect.right = floorf(rect.right); + rect.top = floorf(rect.top); + rect.bottom = floorf(rect.bottom); + + // save the clipping constraints of the view + view->PushState(); + + // set clipping constraints to updateRect + BRegion clipping(updateRect); + view->ConstrainClippingRegion(&clipping); + + rgb_color edgeShadowColor; + rgb_color edgeLightColor; + rgb_color frameShadowColor; + rgb_color frameLightColor; + rgb_color bevelShadowColor; + rgb_color bevelLightColor; + BGradientLinear fillGradient; + fillGradient.SetStart(rect.LeftTop() + BPoint(3, 3)); + fillGradient.SetEnd(rect.LeftBottom() + BPoint(3, -3)); + + if ((flags & B_DISABLED) != 0) { + edgeLightColor = base; + edgeShadowColor = base; + frameLightColor = tint_color(base, 1.0); + frameShadowColor = tint_color(base, 1.30); + bevelLightColor = tint_color(base, 0.8); + bevelShadowColor = tint_color(base, 1.07); + fillGradient.AddColor(tint_color(base, 0.85), 0); + fillGradient.AddColor(base, 255); + } else { + edgeLightColor = tint_color(base, 0.95); + edgeShadowColor = tint_color(base, 1.03); + frameLightColor = tint_color(base, 1.30); + frameShadowColor = tint_color(base, 1.30); + bevelLightColor = tint_color(base, 0.9); + bevelShadowColor = tint_color(base, 1.07); + fillGradient.AddColor(tint_color(base, 0.95), 0); + fillGradient.AddColor(tint_color(base, 1.0), 255); + } + + static const float kRoundCornerRadius = 2.0f; + + // left top corner dimensions + BRect leftTopCorner(rect); + leftTopCorner.right = floorf(leftTopCorner.left + kRoundCornerRadius); + leftTopCorner.bottom = floorf(rect.top + kRoundCornerRadius); + + // right top corner dimensions + BRect rightTopCorner(rect); + rightTopCorner.left = floorf(rightTopCorner.right - kRoundCornerRadius); + rightTopCorner.bottom = floorf(rect.top + kRoundCornerRadius); + + // left bottom corner dimensions + BRect leftBottomCorner(rect); + leftBottomCorner.right = floorf(leftBottomCorner.left + kRoundCornerRadius); + leftBottomCorner.top = floorf(rect.bottom - kRoundCornerRadius); + + // right bottom corner dimensions + BRect rightBottomCorner(rect); + rightBottomCorner.left = floorf(rightBottomCorner.right + - kRoundCornerRadius); + rightBottomCorner.top = floorf(rect.bottom - kRoundCornerRadius); + + switch (side) { + case B_TOP_BORDER: + clipping.Exclude(leftTopCorner); + clipping.Exclude(rightTopCorner); + + // draw the left top corner + _DrawRoundCornerLeftTop(view, leftTopCorner, updateRect, base, + edgeShadowColor, frameLightColor, bevelLightColor, + fillGradient); + // draw the right top corner + _DrawRoundCornerRightTop(view, rightTopCorner, updateRect, base, + edgeShadowColor, edgeLightColor, frameLightColor, + frameShadowColor, bevelLightColor, bevelShadowColor, + fillGradient); + break; + case B_BOTTOM_BORDER: + clipping.Exclude(leftBottomCorner); + clipping.Exclude(rightBottomCorner); + + // draw the left bottom corner + _DrawRoundCornerLeftBottom(view, leftBottomCorner, updateRect, base, + edgeShadowColor, edgeLightColor, frameLightColor, + frameShadowColor, bevelLightColor, bevelShadowColor, + fillGradient); + // draw the right bottom corner + _DrawRoundCornerRightBottom(view, rightBottomCorner, updateRect, + base, edgeLightColor, frameShadowColor, bevelShadowColor, + fillGradient); + break; + case B_LEFT_BORDER: + clipping.Exclude(leftTopCorner); + clipping.Exclude(leftBottomCorner); + + // draw the left top corner + _DrawRoundCornerLeftTop(view, leftTopCorner, updateRect, base, + edgeShadowColor, frameLightColor, bevelLightColor, + fillGradient); + // draw the left bottom corner + _DrawRoundCornerLeftBottom(view, leftBottomCorner, updateRect, base, + edgeShadowColor, edgeLightColor, frameLightColor, + frameShadowColor, bevelLightColor, bevelShadowColor, + fillGradient); + break; + case B_RIGHT_BORDER: + clipping.Exclude(rightTopCorner); + clipping.Exclude(rightBottomCorner); + + // draw the right top corner + _DrawRoundCornerRightTop(view, rightTopCorner, updateRect, base, + edgeShadowColor, edgeLightColor, frameLightColor, + frameShadowColor, bevelLightColor, bevelShadowColor, + fillGradient); + // draw the right bottom corner + _DrawRoundCornerRightBottom(view, rightBottomCorner, updateRect, + base, edgeLightColor, frameShadowColor, bevelShadowColor, + fillGradient); + break; + } + + // clip out the corners + view->ConstrainClippingRegion(&clipping); + + uint32 bordersToDraw = 0; + switch (side) { + case B_TOP_BORDER: + bordersToDraw = (B_LEFT_BORDER | B_TOP_BORDER | B_RIGHT_BORDER); + break; + case B_BOTTOM_BORDER: + bordersToDraw = (B_LEFT_BORDER | B_BOTTOM_BORDER | B_RIGHT_BORDER); + break; + case B_LEFT_BORDER: + bordersToDraw = (B_LEFT_BORDER | B_BOTTOM_BORDER | B_TOP_BORDER); + break; + case B_RIGHT_BORDER: + bordersToDraw = (B_RIGHT_BORDER | B_BOTTOM_BORDER | B_TOP_BORDER); + break; + } + + // draw the rest of frame and fill + _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, edgeLightColor, + edgeLightColor, borders); + if (side == B_TOP_BORDER || side == B_BOTTOM_BORDER) { + if ((borders & B_LEFT_BORDER) == 0) + rect.left++; + if ((borders & B_RIGHT_BORDER) == 0) + rect.right--; + } else if (side == B_LEFT_BORDER || side == B_RIGHT_BORDER) { + if ((borders & B_TOP_BORDER) == 0) + rect.top++; + if ((borders & B_BOTTOM_BORDER) == 0) + rect.bottom--; + } + + _DrawFrame(view, rect, frameLightColor, frameLightColor, frameShadowColor, + frameShadowColor, bordersToDraw); + + _DrawFrame(view, rect, bevelLightColor, bevelLightColor, bevelShadowColor, + bevelShadowColor); + + view->FillRect(rect, fillGradient); + + // restore the clipping constraints of the view + view->PopState(); +} + + +void +FlatControlLook::DrawSplitter(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, orientation orientation, uint32 flags, + uint32 borders) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + rgb_color background; + if ((flags & (B_CLICKED | B_ACTIVATED)) != 0) + background = tint_color(base, B_DARKEN_1_TINT); + else + background = base; + + rgb_color light = tint_color(background, 1.9); + rgb_color shadow = tint_color(background, 1.9); + + // frame + if (borders != 0 && rect.Width() > 3 && rect.Height() > 3) + DrawRaisedBorder(view, rect, updateRect, background, flags, borders); + + // dots and rest of background + if (orientation == B_HORIZONTAL) { + if (rect.Width() > 2) { + // background on left/right + BRegion region(rect); + rect.left = floorf((rect.left + rect.right) / 2.0 - 0.5); + rect.right = rect.left + 1; + region.Exclude(rect); + view->SetHighColor(background); + view->FillRegion(®ion); + } + + BPoint dot = rect.LeftTop(); + BPoint stop = rect.LeftBottom(); + int32 num = 1; + while (dot.y <= stop.y) { + rgb_color col1; + rgb_color col2; + switch (num) { + case 1: + col1 = background; + col2 = background; + break; + case 2: + col1 = shadow; + col2 = background; + break; + case 3: + default: + col1 = background; + col2 = light; + num = 0; + break; + } + view->SetHighColor(col1); + view->StrokeLine(dot, dot, B_SOLID_LOW); + view->SetHighColor(col2); + dot.x++; + view->StrokeLine(dot, dot, B_SOLID_LOW); + dot.x -= 1.0; + // next pixel + num++; + dot.y++; + } + } else { + if (rect.Height() > 2) { + // background on left/right + BRegion region(rect); + rect.top = floorf((rect.top + rect.bottom) / 2.0 - 0.5); + rect.bottom = rect.top + 1; + region.Exclude(rect); + view->SetHighColor(background); + view->FillRegion(®ion); + } + + BPoint dot = rect.LeftTop(); + BPoint stop = rect.RightTop(); + int32 num = 1; + while (dot.x <= stop.x) { + rgb_color col1; + rgb_color col2; + switch (num) { + case 1: + col1 = background; + col2 = background; + break; + case 2: + col1 = shadow; + col2 = background; + break; + case 3: + default: + col1 = background; + col2 = light; + num = 0; + break; + } + view->SetHighColor(col1); + view->StrokeLine(dot, dot, B_SOLID_LOW); + view->SetHighColor(col2); + dot.y++; + view->StrokeLine(dot, dot, B_SOLID_LOW); + dot.y -= 1.0; + // next pixel + num++; + dot.x++; + } + } +} + + +// #pragma mark - + + +void +FlatControlLook::DrawBorder(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, border_style borderStyle, uint32 flags, + uint32 borders) +{ + if (borderStyle == B_NO_BORDER) + return; + + rgb_color scrollbarFrameColor = tint_color(base, 1.1); + + _DrawFrame(view, rect, scrollbarFrameColor, scrollbarFrameColor, + scrollbarFrameColor, scrollbarFrameColor, borders); +} + + +void +FlatControlLook::DrawRaisedBorder(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders) +{ + rgb_color lightColor; + rgb_color shadowColor; + + if ((flags & B_DISABLED) != 0) { + lightColor = base; + shadowColor = base; + } else { + lightColor = tint_color(base, 1.0); + shadowColor = tint_color(base, 1.0); + } + + _DrawFrame(view, rect, shadowColor, shadowColor, shadowColor, shadowColor, + borders); +} + + +void +HaikuControlLook::DrawTextControlBorder(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders) +{ + if (!rect.Intersects(updateRect)) + return; + + rgb_color dark1BorderColor; + rgb_color dark2BorderColor; + rgb_color customColor2; + rgb_color navigationColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); + rgb_color invalidColor = ui_color(B_FAILURE_COLOR); + + customColor2 = tint_color(base, 1.08); + // if the color BACKGROUND used is too dark, then make it lighter using the + // same as B_CONTROL_TEXT_COLOR + if (base.red + base.green + base.blue <= 128 * 3) { + customColor2 = base; + } + + dark1BorderColor = customColor2; + dark2BorderColor = customColor2; + + if ((flags & B_DISABLED) != 0) { + _DrawOuterResessedFrame(view, rect, base, 0.0, 1.0, flags, borders); + + if ((flags & B_BLEND_FRAME) != 0) + dark1BorderColor = (rgb_color){ 0, 0, 0, 40 }; + else + dark1BorderColor = tint_color(base, 1.0); + dark2BorderColor = dark1BorderColor; + } + else if ((flags & B_CLICKED) != 0) { + dark1BorderColor = tint_color(customColor2, 1.9); + dark2BorderColor = tint_color(customColor2, 1.9); + + // BCheckBox uses this to indicate the clicked state... + _DrawFrame(view, rect, + dark1BorderColor, dark1BorderColor, + dark2BorderColor, dark2BorderColor); + + dark2BorderColor = dark1BorderColor; + } + else { + _DrawOuterResessedFrame(view, rect, base, 1.0, 1.0, flags, borders); + + if ((flags & B_BLEND_FRAME) != 0) { + dark1BorderColor = customColor2; + dark2BorderColor = customColor2; + } else { + dark1BorderColor = customColor2; + dark2BorderColor = customColor2; + } + } + + if ((flags & B_DISABLED) == 0 && (flags & B_FOCUSED) != 0) { + dark1BorderColor = navigationColor; + dark2BorderColor = navigationColor; + } + + if ((flags & B_DISABLED) == 0 && (flags & B_INVALID) != 0) { + dark1BorderColor = invalidColor; + dark2BorderColor = invalidColor; + } + + if ((flags & B_BLEND_FRAME) != 0) { + drawing_mode oldMode = view->DrawingMode(); + view->SetDrawingMode(B_OP_ALPHA); + + _DrawFrame(view, rect, + dark1BorderColor, dark1BorderColor, + dark2BorderColor, dark2BorderColor, borders); + + view->SetDrawingMode(oldMode); + } else { + _DrawFrame(view, rect, + dark1BorderColor, dark1BorderColor, + dark2BorderColor, dark2BorderColor, borders); + } +} + + +void +HaikuControlLook::DrawGroupFrame(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, uint32 borders) +{ + rgb_color frameColor = tint_color(base, 1.1); + + // if the base color is too dark, then lets make it lighter + if (base.red + base.green + base.blue <= 128 * 3) { + frameColor = tint_color(base, 0.95);; + } + + // Draws only one flat frame: + _DrawFrame(view, rect, frameColor, frameColor, frameColor, frameColor, + borders); +} + + +void +FlatControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders, orientation orientation) +{ + _DrawButtonBackground(view, rect, updateRect, 1.5f, 1.5f, 1.5f, 1.5f, + base, true, flags, borders, orientation); +} + + +void +FlatControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, + const BRect& updateRect, float radius, const rgb_color& base, uint32 flags, + uint32 borders, orientation orientation) +{ + _DrawButtonBackground(view, rect, updateRect, radius, radius, radius, + radius, base, true, flags, borders, orientation); +} + + +void +FlatControlLook::DrawButtonWithPopUpBackground(BView* view, BRect& rect, + const BRect& updateRect, float leftTopRadius, float rightTopRadius, + float leftBottomRadius, float rightBottomRadius, const rgb_color& base, + uint32 flags, uint32 borders, orientation orientation) +{ + _DrawButtonBackground(view, rect, updateRect, leftTopRadius, + rightTopRadius, leftBottomRadius, rightBottomRadius, base, true, flags, + borders, orientation); +} + + +// #pragma mark - + + +void +HaikuControlLook::_DrawButtonFrame(BView* view, BRect& rect, + const BRect& updateRect, float leftTopRadius, float rightTopRadius, + float leftBottomRadius, float rightBottomRadius, const rgb_color& base, + const rgb_color& background, float contrast, float brightness, + uint32 flags, uint32 borders) +{ + + rgb_color customColor = background; // custom color for borders + rgb_color customColor2 = tint_color(background, 1.3); + + // if the color BACKGROUND used is too dark, then make it lighter using + // the same as B_CONTROL_TEXT_COLOR + if (base.red + base.green + base.blue <= 128 * 3) { + customColor2 = tint_color(ui_color(B_CONTROL_TEXT_COLOR), 1.55); + } + + if (!rect.IsValid()) + return; + + // save the clipping constraints of the view + view->PushState(); + + // set clipping constraints to updateRect + BRegion clipping(updateRect); + view->ConstrainClippingRegion(&clipping); + + // If the button is flat and neither activated nor otherwise highlighted + // (mouse hovering or focussed), draw it flat. + if ((flags & B_FLAT) != 0 + && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0 + && ((flags & (B_HOVER | B_FOCUSED)) == 0 + || (flags & B_DISABLED) != 0)) { + _DrawFrame(view, rect, customColor, customColor, customColor, + customColor, borders); + view->PopState(); + return; + } + + // outer edge colors + rgb_color edgeLightColor; + rgb_color edgeShadowColor; + + // default button frame color + rgb_color defaultIndicatorColor = customColor; + rgb_color cornerBgColor; + + if ((flags & B_DISABLED) != 0) { + defaultIndicatorColor = disable_color(defaultIndicatorColor, + customColor); + } + + drawing_mode oldMode = view->DrawingMode(); + + // frame colors + rgb_color frameLightColor = customColor; //_FrameLightColor(base, flags); + rgb_color frameShadowColor = customColor; //_FrameShadowColor(base, flags); + +#if 0 + if ((flags & B_DEFAULT_BUTTON) != 0) { + cornerBgColor = customColor; + if ((flags & B_BLEND_FRAME) != 0) { + // set the background color to transparent for the case + // that we are on the desktop + cornerBgColor.alpha = 0; + view->SetDrawingMode(B_OP_ALPHA); + } + + customColor2 = tint_color(ui_color(B_WINDOW_TAB_COLOR), 1.0); + + if (base.red + base.green + base.blue <= 128 * 3) { + customColor2 = tint_color(ui_color(B_WINDOW_TAB_COLOR), 1.4); + } + edgeLightColor = customColor2; + edgeShadowColor = customColor2; + + + // draw default button indicator + // Allow a 1-pixel border of the background to come through. + rect.InsetBy(1, 1); + view->SetHighColor(tint_color(customColor, 1.2)); + view->StrokeRoundRect(rect, leftTopRadius, leftTopRadius); + rect.InsetBy(0, 0); + } else { +#endif + cornerBgColor = customColor; + if ((flags & B_BLEND_FRAME) != 0) { + // set the background color to transparent for the case + // that we are on the desktop + cornerBgColor.alpha = 0; + view->SetDrawingMode(B_OP_ALPHA); + } + + edgeLightColor = customColor2; + edgeShadowColor = customColor2; +#if 0 + } +#endif + + // rounded corners + if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0 + && leftTopRadius > 0) { + // draw left top rounded corner + BRect leftTopCorner(floorf(rect.left), floorf(rect.top), + floorf(rect.left + leftTopRadius), + floorf(rect.top + leftTopRadius)); + clipping.Exclude(leftTopCorner); + _DrawRoundCornerFrameLeftTop(view, leftTopCorner, updateRect, + cornerBgColor, edgeShadowColor, frameLightColor); + } + + if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0 + && rightTopRadius > 0) { + // draw right top rounded corner + BRect rightTopCorner(floorf(rect.right - rightTopRadius), + floorf(rect.top), floorf(rect.right), + floorf(rect.top + rightTopRadius)); + clipping.Exclude(rightTopCorner); + _DrawRoundCornerFrameRightTop(view, rightTopCorner, updateRect, + cornerBgColor, edgeShadowColor, edgeLightColor, + frameLightColor, frameShadowColor); + } + + if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 + && leftBottomRadius > 0) { + // draw left bottom rounded corner + BRect leftBottomCorner(floorf(rect.left), + floorf(rect.bottom - leftBottomRadius), + floorf(rect.left + leftBottomRadius), floorf(rect.bottom)); + clipping.Exclude(leftBottomCorner); + _DrawRoundCornerFrameLeftBottom(view, leftBottomCorner, updateRect, + cornerBgColor, edgeShadowColor, edgeLightColor, + frameLightColor, frameShadowColor); + } + + if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 + && rightBottomRadius > 0) { + // draw right bottom rounded corner + BRect rightBottomCorner(floorf(rect.right - rightBottomRadius), + floorf(rect.bottom - rightBottomRadius), floorf(rect.right), + floorf(rect.bottom)); + clipping.Exclude(rightBottomCorner); + _DrawRoundCornerFrameRightBottom(view, rightBottomCorner, + updateRect, cornerBgColor, edgeLightColor, frameShadowColor); + } + + // clip out the corners + view->ConstrainClippingRegion(&clipping); + +#if 0 + // draw outer edge only for default button!!! B_SUCCESS_COLOR + if ((flags & B_DEFAULT_BUTTON) != 0) { + _DrawOuterResessedFrame(view, rect, ui_color(B_WINDOW_TAB_COLOR), + contrast * ((flags & B_DISABLED) != 0 ? 0.3 : 0.8), + brightness * ((flags & B_DISABLED) != 0 ? 0.3 : 0.9), + flags, borders); + } +#endif + + view->SetDrawingMode(oldMode); + + // draw frame + if ((flags & B_BLEND_FRAME) != 0) { + drawing_mode oldDrawingMode = view->DrawingMode(); + view->SetDrawingMode(B_OP_ALPHA); + + _DrawFrame(view, rect, customColor2, customColor2, + customColor2, customColor2, borders); + + view->SetDrawingMode(oldDrawingMode); + } else { + _DrawFrame(view, rect, customColor2, customColor2, + customColor2, customColor2, borders); + } + + // restore the clipping constraints of the view + view->PopState(); +} + + +void +FlatControlLook::_DrawOuterResessedFrame(BView* view, BRect& rect, + const rgb_color& base, float contrast, float brightness, uint32 flags, + uint32 borders) +{ + rgb_color edgeShadowColor = tint_color(base, 1.0); + + if ((flags & B_BLEND_FRAME) != 0) { + // assumes the background has already been painted + drawing_mode oldDrawingMode = view->DrawingMode(); + view->SetDrawingMode(B_OP_ALPHA); + + _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, + edgeShadowColor, edgeShadowColor, borders); + + view->SetDrawingMode(oldDrawingMode); + } else { + _DrawFrame(view, rect, edgeShadowColor, edgeShadowColor, + edgeShadowColor, edgeShadowColor, borders); + } +} + + +void +FlatControlLook::_DrawButtonBackground(BView* view, BRect& rect, + const BRect& updateRect, float leftTopRadius, float rightTopRadius, + float leftBottomRadius, float rightBottomRadius, const rgb_color& base, + bool popupIndicator, uint32 flags, uint32 borders, orientation orientation) +{ + rgb_color customColor = base; + + if (!rect.IsValid()) + return; + + // save the clipping constraints of the view + view->PushState(); + + // set clipping constraints to updateRect + BRegion clipping(updateRect); + view->ConstrainClippingRegion(&clipping); + + // If is a default button, set backcolor to the tab color. + if ((flags & B_DEFAULT_BUTTON) != 0) + { + rgb_color textcolor = ui_color(B_CONTROL_TEXT_COLOR); + //if the text color is too light, then make it using the same as B_CONTROL_TEXT_COLOR + if (textcolor.red + textcolor.green + textcolor.blue >= 128 * 3) + customColor = tint_color(ui_color(B_WINDOW_TAB_COLOR), 1.4); + else + customColor = ui_color(B_WINDOW_TAB_COLOR); + } + + // If the button is flat and neither activated nor otherwise highlighted + // (mouse hovering or focussed), draw it flat. + if ((flags & B_FLAT) != 0 + && (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED)) == 0 + && ((flags & (B_HOVER | B_FOCUSED)) == 0 + || (flags & B_DISABLED) != 0)) { + _DrawFlatButtonBackground(view, rect, updateRect, customColor, popupIndicator, + flags, borders, orientation); + } else { + _DrawNonFlatButtonBackground(view, rect, updateRect, clipping, + leftTopRadius, rightTopRadius, leftBottomRadius, rightBottomRadius, + customColor, popupIndicator, flags, borders, orientation); + } + + // restore the clipping constraints of the view + view->PopState(); +} + + +void +FlatControlLook::_DrawNonFlatButtonBackground(BView* view, BRect& rect, + const BRect& updateRect, BRegion& clipping, float leftTopRadius, + float rightTopRadius, float leftBottomRadius, float rightBottomRadius, + const rgb_color& base, bool popupIndicator, uint32 flags, uint32 borders, + orientation orientation) +{ + // inner bevel colors + rgb_color bevelLightColor = _BevelLightColor(base, flags); + rgb_color bevelShadowColor = _BevelShadowColor(base, flags); + + // button background color + rgb_color buttonBgColor; + + buttonBgColor = tint_color(base, 1.04); + + // surface top gradient + BGradientLinear fillGradient; + _MakeButtonGradient(fillGradient, rect, base, flags, orientation); + + // rounded corners + + if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0 + && leftTopRadius > 0) { + // draw left top rounded corner + BRect leftTopCorner(floorf(rect.left), floorf(rect.top), + floorf(rect.left + leftTopRadius - 2.0), + floorf(rect.top + leftTopRadius - 2.0)); + clipping.Exclude(leftTopCorner); + _DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect, + bevelLightColor, fillGradient); + } + + if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0 + && rightTopRadius > 0) { + // draw right top rounded corner + BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0), + floorf(rect.top), floorf(rect.right), + floorf(rect.top + rightTopRadius - 2.0)); + clipping.Exclude(rightTopCorner); + _DrawRoundCornerBackgroundRightTop(view, rightTopCorner, + updateRect, bevelLightColor, bevelShadowColor, fillGradient); + } + + if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 + && leftBottomRadius > 0) { + // draw left bottom rounded corner + BRect leftBottomCorner(floorf(rect.left), + floorf(rect.bottom - leftBottomRadius + 2.0), + floorf(rect.left + leftBottomRadius - 2.0), + floorf(rect.bottom)); + clipping.Exclude(leftBottomCorner); + _DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner, + updateRect, bevelLightColor, bevelShadowColor, fillGradient); + } + + if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 + && rightBottomRadius > 0) { + // draw right bottom rounded corner + BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0), + floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right), + floorf(rect.bottom)); + clipping.Exclude(rightBottomCorner); + _DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner, + updateRect, bevelShadowColor, fillGradient); + } + + // clip out the corners + view->ConstrainClippingRegion(&clipping); + + // draw inner bevel + + if ((flags & B_ACTIVATED) != 0) { + view->BeginLineArray(4); + + // shadow along left/top borders + if (borders & B_LEFT_BORDER) { + view->AddLine(BPoint(rect.left, rect.top), + BPoint(rect.left, rect.bottom), buttonBgColor); + rect.left++; + } + if (borders & B_TOP_BORDER) { + view->AddLine(BPoint(rect.left, rect.top), + BPoint(rect.right, rect.top), buttonBgColor); + rect.top++; + } + + // softer shadow along left/top borders + if (borders & B_LEFT_BORDER) { + view->AddLine(BPoint(rect.left, rect.top), + BPoint(rect.left, rect.bottom), buttonBgColor); + rect.left++; + } + if (borders & B_TOP_BORDER) { + view->AddLine(BPoint(rect.left, rect.top), + BPoint(rect.right, rect.top), buttonBgColor); + rect.top++; + } + + view->EndLineArray(); + } else { + _DrawFrame(view, rect, + buttonBgColor, buttonBgColor, + buttonBgColor, buttonBgColor, + buttonBgColor, buttonBgColor, borders); + } + + if (popupIndicator) { + BRect indicatorRect(rect); + rect.right -= kButtonPopUpIndicatorWidth; + indicatorRect.left = rect.right + 3; + // 2 pixels for the separator + + // Even when depressed we want the pop-up indicator background and + // separator to cover the area up to the top. + if ((flags & B_ACTIVATED) != 0) + indicatorRect.top--; + + // draw the separator + rgb_color separatorBaseColor = base; + if ((flags & B_ACTIVATED) != 0) + separatorBaseColor = tint_color(base, B_DARKEN_1_TINT); + + //rgb_color separatorLightColor = tint_color(base, B_DARKEN_1_TINT); + rgb_color separatorShadowColor = tint_color(base, B_DARKEN_1_TINT); + + view->BeginLineArray(2); + + view->AddLine(BPoint(indicatorRect.left - 2, indicatorRect.top), + BPoint(indicatorRect.left - 2, indicatorRect.bottom), + separatorShadowColor); + view->AddLine(BPoint(indicatorRect.left - 1, indicatorRect.top), + BPoint(indicatorRect.left - 1, indicatorRect.bottom), + separatorShadowColor); + + view->EndLineArray(); + + // draw background and pop-up marker + _DrawMenuFieldBackgroundInside(view, indicatorRect, updateRect, + 1.5f, rightTopRadius, 1.5f, rightBottomRadius, base, flags, 0); + + if ((flags & B_ACTIVATED) != 0) + indicatorRect.top++; + + _DrawPopUpMarker(view, indicatorRect, ui_color(B_MENU_ITEM_TEXT_COLOR), flags); + } + + // fill in the background + view->FillRect(rect, fillGradient); +} + + +void +HaikuControlLook::_DrawPopUpMarker(BView* view, const BRect& rect, + const rgb_color& base, uint32 flags) +{ + BPoint center(roundf((rect.left + rect.right) / 2.0), + roundf((rect.top + rect.bottom) / 2.0)); + BPoint triangle[3]; + triangle[0] = center + BPoint(-2.5, -0.5); + triangle[1] = center + BPoint(2.5, -0.5); + triangle[2] = center + BPoint(0.0, 2.0); + + uint32 viewFlags = view->Flags(); + view->SetFlags(viewFlags | B_SUBPIXEL_PRECISE); + + rgb_color markColor; + if ((flags & B_DISABLED) != 0) + markColor = tint_color(base, 1.0); + else + markColor = tint_color(base, 1.0); + + view->SetHighColor(markColor); + view->FillTriangle(triangle[0], triangle[1], triangle[2]); + + view->SetFlags(viewFlags); +} + + +void +FlatControlLook::_DrawMenuFieldBackgroundOutside(BView* view, BRect& rect, + const BRect& updateRect, float leftTopRadius, float rightTopRadius, + float leftBottomRadius, float rightBottomRadius, const rgb_color& base, + bool popupIndicator, uint32 flags) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + if (popupIndicator) { + BRect leftRect(rect); + leftRect.right -= 10; + + BRect rightRect(rect); + rightRect.left = rightRect.right - 9; + + _DrawMenuFieldBackgroundInside(view, leftRect, updateRect, + leftTopRadius, 1.5f, leftBottomRadius, 1.5f, tint_color(base, 0.95), flags, + B_LEFT_BORDER | B_TOP_BORDER | B_BOTTOM_BORDER); + + _DrawMenuFieldBackgroundInside(view, rightRect, updateRect, + 1.5f, rightTopRadius, 1.5f, rightBottomRadius, tint_color(base, 1.04), flags, + B_TOP_BORDER | B_RIGHT_BORDER | B_BOTTOM_BORDER); + + _DrawPopUpMarker(view, rightRect, ui_color(B_MENU_ITEM_TEXT_COLOR), flags); + + // draw a line on the left of the popup frame, this line separate the + // arrow to the bottom control + rgb_color bevelShadowColor = tint_color(base, 1.1); + view->SetHighColor(bevelShadowColor); + BPoint leftTopCorner(floorf(rightRect.left - 1.0), + floorf(rightRect.top - 1.0)); + BPoint leftBottomCorner(floorf(rightRect.left - 1.0), + floorf(rightRect.bottom + 1.0)); + view->StrokeLine(leftTopCorner, leftBottomCorner); + + rect = leftRect; + } else { + _DrawMenuFieldBackgroundInside(view, rect, updateRect, leftTopRadius, + rightTopRadius, leftBottomRadius, rightBottomRadius, base, flags, + B_TOP_BORDER | B_RIGHT_BORDER | B_BOTTOM_BORDER); + } +} + + +void +FlatControlLook::_DrawMenuFieldBackgroundInside(BView* view, BRect& rect, + const BRect& updateRect, float leftTopRadius, float rightTopRadius, + float leftBottomRadius, float rightBottomRadius, const rgb_color& base, + uint32 flags, uint32 borders) +{ + if (!rect.IsValid() || !rect.Intersects(updateRect)) + return; + + // save the clipping constraints of the view + view->PushState(); + + // set clipping constraints to updateRect + BRegion clipping(updateRect); + view->ConstrainClippingRegion(&clipping); + + // frame colors + rgb_color frameLightColor = _FrameLightColor(base, flags); + rgb_color frameShadowColor = _FrameShadowColor(base, flags); + + // indicator background color + rgb_color indicatorBase; + if ((borders & B_LEFT_BORDER) != 0) + indicatorBase = base; + else { + if ((flags & B_DISABLED) != 0) + indicatorBase = tint_color(base, 1.5); + else + indicatorBase = tint_color(base, 0.97); + } + + // bevel colors + rgb_color cornerColor = tint_color(indicatorBase, 1.0); + rgb_color bevelColor1 = tint_color(indicatorBase, 1.0); + rgb_color bevelColor2 = tint_color(indicatorBase, 1.0); + rgb_color bevelColor3 = tint_color(indicatorBase, 1.0); + + if ((flags & B_DISABLED) != 0) { + cornerColor = tint_color(indicatorBase, 1.0); + bevelColor1 = tint_color(indicatorBase, 1.0); + bevelColor2 = tint_color(indicatorBase, 1.0); + bevelColor3 = tint_color(indicatorBase, 1.0); + } else { + cornerColor = tint_color(indicatorBase, 1.0); + bevelColor1 = tint_color(indicatorBase, 1.0); + bevelColor2 = tint_color(indicatorBase, 1.0); + bevelColor3 = tint_color(indicatorBase, 1.0); + } + + // surface top gradient + BGradientLinear fillGradient; + _MakeButtonGradient(fillGradient, rect, indicatorBase, flags); + + // rounded corners + + if ((borders & B_LEFT_BORDER) != 0 && (borders & B_TOP_BORDER) != 0 + && leftTopRadius > 0) { + // draw left top rounded corner + BRect leftTopCorner(floorf(rect.left), floorf(rect.top), + floorf(rect.left + leftTopRadius - 2.0), + floorf(rect.top + leftTopRadius - 2.0)); + clipping.Exclude(leftTopCorner); + + BRegion cornerClipping(leftTopCorner); + view->ConstrainClippingRegion(&cornerClipping); + + BRect ellipseRect(leftTopCorner); + ellipseRect.InsetBy(-1.0, -1.0); + ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; + ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; + + // draw the frame (again) + view->SetHighColor(frameLightColor); + view->FillEllipse(ellipseRect); + + // draw the bevel and background + _DrawRoundCornerBackgroundLeftTop(view, leftTopCorner, updateRect, + bevelColor1, fillGradient); + } + + if ((borders & B_TOP_BORDER) != 0 && (borders & B_RIGHT_BORDER) != 0 + && rightTopRadius > 0) { + // draw right top rounded corner + BRect rightTopCorner(floorf(rect.right - rightTopRadius + 2.0), + floorf(rect.top), floorf(rect.right), + floorf(rect.top + rightTopRadius - 2.0)); + clipping.Exclude(rightTopCorner); + + BRegion cornerClipping(rightTopCorner); + view->ConstrainClippingRegion(&cornerClipping); + + BRect ellipseRect(rightTopCorner); + ellipseRect.InsetBy(-1.0, -1.0); + ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; + ellipseRect.bottom = ellipseRect.top + ellipseRect.Height() * 2; + + // draw the frame (again) + if (frameLightColor == frameShadowColor) { + view->SetHighColor(frameLightColor); + view->FillEllipse(ellipseRect); + } else { + BGradientLinear gradient; + gradient.AddColor(frameLightColor, 0); + gradient.AddColor(frameShadowColor, 255); + gradient.SetStart(rightTopCorner.LeftTop()); + gradient.SetEnd(rightTopCorner.RightBottom()); + view->FillEllipse(ellipseRect, gradient); + } + + // draw the bevel and background + _DrawRoundCornerBackgroundRightTop(view, rightTopCorner, updateRect, + bevelColor1, bevelColor3, fillGradient); + } + + if ((borders & B_LEFT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 + && leftBottomRadius > 0) { + // draw left bottom rounded corner + BRect leftBottomCorner(floorf(rect.left), + floorf(rect.bottom - leftBottomRadius + 2.0), + floorf(rect.left + leftBottomRadius - 2.0), + floorf(rect.bottom)); + clipping.Exclude(leftBottomCorner); + + BRegion cornerClipping(leftBottomCorner); + view->ConstrainClippingRegion(&cornerClipping); + + BRect ellipseRect(leftBottomCorner); + ellipseRect.InsetBy(-1.0, -1.0); + ellipseRect.right = ellipseRect.left + ellipseRect.Width() * 2; + ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; + + // draw the frame (again) + if (frameLightColor == frameShadowColor) { + view->SetHighColor(frameLightColor); + view->FillEllipse(ellipseRect); + } else { + BGradientLinear gradient; + gradient.AddColor(frameLightColor, 0); + gradient.AddColor(frameShadowColor, 255); + gradient.SetStart(leftBottomCorner.LeftTop()); + gradient.SetEnd(leftBottomCorner.RightBottom()); + view->FillEllipse(ellipseRect, gradient); + } + + // draw the bevel and background + _DrawRoundCornerBackgroundLeftBottom(view, leftBottomCorner, + updateRect, bevelColor2, bevelColor3, fillGradient); + } + + if ((borders & B_RIGHT_BORDER) != 0 && (borders & B_BOTTOM_BORDER) != 0 + && rightBottomRadius > 0) { + // draw right bottom rounded corner + BRect rightBottomCorner(floorf(rect.right - rightBottomRadius + 2.0), + floorf(rect.bottom - rightBottomRadius + 2.0), floorf(rect.right), + floorf(rect.bottom)); + clipping.Exclude(rightBottomCorner); + + BRegion cornerClipping(rightBottomCorner); + view->ConstrainClippingRegion(&cornerClipping); + + BRect ellipseRect(rightBottomCorner); + ellipseRect.InsetBy(-1.0, -1.0); + ellipseRect.left = ellipseRect.right - ellipseRect.Width() * 2; + ellipseRect.top = ellipseRect.bottom - ellipseRect.Height() * 2; + + // draw the frame (again) + view->SetHighColor(frameShadowColor); + view->FillEllipse(ellipseRect); + + // draw the bevel and background + _DrawRoundCornerBackgroundRightBottom(view, rightBottomCorner, + updateRect, bevelColor3, fillGradient); + } + + // clip out the corners + view->ConstrainClippingRegion(&clipping); + + // draw the bevel + _DrawFrame(view, rect, + bevelColor2, bevelColor1, + bevelColor3, bevelColor3, + cornerColor, cornerColor, + borders); + + // fill in the background + view->FillRect(rect, fillGradient); + + // restore the clipping constraints of the view + view->PopState(); +} + + +rgb_color +FlatControlLook::_EdgeLightColor(const rgb_color& base, float contrast, + float brightness, uint32 flags) +{ + return base; +} + + +rgb_color +FlatControlLook::_EdgeShadowColor(const rgb_color& base, float contrast, + float brightness, uint32 flags) +{ + return base; +} + + + + +rgb_color +HaikuControlLook::_BevelLightColor(const rgb_color& base, uint32 flags) +{ + rgb_color bevelLightColor = tint_color(base, 1.0); + return bevelLightColor; +} + + +rgb_color +HaikuControlLook::_BevelShadowColor(const rgb_color& base, uint32 flags) +{ + rgb_color bevelShadowColor = tint_color(base, 1.0); + return bevelShadowColor; +} + + +void +HaikuControlLook::_MakeGradient(BGradientLinear& gradient, const BRect& rect, + const rgb_color& base, float topTint, float bottomTint, + orientation orientation) const +{ + gradient.AddColor(tint_color(base, 0.97), 0); + gradient.AddColor(tint_color(base, 1.0), 255); + gradient.SetStart(rect.LeftTop()); + if (orientation == B_HORIZONTAL) + gradient.SetEnd(rect.LeftBottom()); + else + gradient.SetEnd(rect.RightTop()); +} + + +void +HaikuControlLook::_MakeGlossyGradient(BGradientLinear& gradient, const BRect& rect, + const rgb_color& base, float topTint, float middle1Tint, + float middle2Tint, float bottomTint, + orientation orientation) const +{ + gradient.AddColor(tint_color(base, topTint), 0); + gradient.AddColor(tint_color(base, bottomTint), 255); + gradient.SetStart(rect.LeftTop()); + if (orientation == B_HORIZONTAL) + gradient.SetEnd(rect.LeftBottom()); + else + gradient.SetEnd(rect.RightTop()); +} + + +void +HaikuControlLook::_MakeButtonGradient(BGradientLinear& gradient, BRect& rect, + const rgb_color& base, uint32 flags, orientation orientation) const +{ + float topTint = 0.99; + float middleTint1 = 0.99; + float middleTint2 = 1.0; + float bottomTint = 1.07; + + if ((flags & B_ACTIVATED) != 0) { + topTint = 1.11; + bottomTint = 1.08; + } + + if ((flags & B_DISABLED) != 0) { + topTint = (topTint + B_NO_TINT) / 2; + middleTint1 = (middleTint1 + B_NO_TINT) / 2; + middleTint2 = (middleTint2 + B_NO_TINT) / 2; + bottomTint = (bottomTint + B_NO_TINT) / 2; + } else if ((flags & B_HOVER) != 0) { + topTint = 1.0; + middleTint1 = 1.0; + middleTint2 = 1.0; + bottomTint = 1.0; + } + + if ((flags & B_ACTIVATED) != 0) { + _MakeGradient(gradient, rect, base, topTint, bottomTint, orientation); + } else { + _MakeGlossyGradient(gradient, rect, base, topTint, middleTint1, + middleTint2, bottomTint, orientation); + } +} + + +} // bprivate + + +extern "C" BControlLook* (instantiate_control_look)(image_id id) +{ + return new (std::nothrow)BPrivate::FlatControlLook(); +} diff --git a/src/add-ons/control_look/FlatControlLook/FlatControlLook.h b/src/add-ons/control_look/FlatControlLook/FlatControlLook.h new file mode 100644 index 0000000000..5ef539c204 --- /dev/null +++ b/src/add-ons/control_look/FlatControlLook/FlatControlLook.h @@ -0,0 +1,174 @@ +/* + * Copyright 2009-2020 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * François Revol, revol@free.fr + * Nahuel Tello, ntello@unarix.com.ar + */ +#ifndef FLAT_CONTROL_LOOK_H +#define FLAT_CONTROL_LOOK_H + + +#include + +#include "HaikuControlLook.h" + + +class BBitmap; +class BControl; +class BGradientLinear; +class BView; + +namespace BPrivate { + +using BPrivate::HaikuControlLook; + +class FlatControlLook : public HaikuControlLook { +public: + FlatControlLook(); + virtual ~FlatControlLook(); + + + virtual void DrawMenuBarBackground(BView* view, BRect& rect, + const BRect& updateRect, + const rgb_color& base, + uint32 flags, + uint32 borders = B_ALL_BORDERS); + virtual void DrawMenuItemBackground(BView* view, + BRect& rect, const BRect& updateRect, + const rgb_color& base, uint32 flags = 0, + uint32 borders = B_ALL_BORDERS); + virtual void DrawMenuFieldFrame(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, + const rgb_color& background, uint32 flags, uint32 borders); + virtual void DrawMenuFieldFrame(BView* view, BRect& rect, + const BRect& updateRect, float radius, const rgb_color& base, + const rgb_color& background, uint32 flags, uint32 borders); + virtual void DrawMenuFieldFrame(BView* view, BRect& rect, + const BRect& updateRect, float leftTopRadius, + float rightTopRadius, float leftBottomRadius, + float rightBottomRadius, const rgb_color& base, + const rgb_color& background, uint32 flags, uint32 borders); + + + virtual void DrawButtonBackground(BView* view, BRect& rect, + const BRect& updateRect, + const rgb_color& base, + uint32 flags = 0, + uint32 borders = B_ALL_BORDERS, + orientation orientation = B_HORIZONTAL); + virtual void DrawButtonBackground(BView* view, BRect& rect, + const BRect& updateRect, + float radius, + const rgb_color& base, + uint32 flags = 0, + uint32 borders = B_ALL_BORDERS, + orientation orientation = B_HORIZONTAL); + virtual void DrawButtonBackground(BView* view, BRect& rect, + const BRect& updateRect, + float leftTopRadius, + float rightTopRadius, + float leftBottomRadius, + float rightBottomRadius, + const rgb_color& base, + uint32 flags = 0, + uint32 borders = B_ALL_BORDERS, + orientation orientation = B_HORIZONTAL); + + void _DrawButtonBackground(BView* view, BRect& rect, + const BRect& updateRect, + float leftTopRadius, + float rightTopRadius, + float leftBottomRadius, + float rightBottomRadius, + const rgb_color& base, + bool popupIndicator = false, + uint32 flags = 0, + uint32 borders = B_ALL_BORDERS, + orientation orientation = B_HORIZONTAL); + void _DrawNonFlatButtonBackground(BView* view, BRect& rect, + const BRect& updateRect, + BRegion& clipping, + float leftTopRadius, + float rightTopRadius, + float leftBottomRadius, + float rightBottomRadius, + const rgb_color& base, + bool popupIndicator, + uint32 flags, + uint32 borders, + orientation orientation); + + virtual void DrawButtonWithPopUpBackground(BView* view, + BRect& rect, const BRect& updateRect, + const rgb_color& base, + uint32 flags = 0, + uint32 borders = B_ALL_BORDERS, + orientation orientation = B_HORIZONTAL); + virtual void DrawButtonWithPopUpBackground(BView* view, + BRect& rect, const BRect& updateRect, + float radius, + const rgb_color& base, + uint32 flags = 0, + uint32 borders = B_ALL_BORDERS, + orientation orientation = B_HORIZONTAL); + virtual void DrawButtonWithPopUpBackground(BView* view, + BRect& rect, const BRect& updateRect, + float leftTopRadius, + float rightTopRadius, + float leftBottomRadius, + float rightBottomRadius, + const rgb_color& base, + uint32 flags = 0, + uint32 borders = B_ALL_BORDERS, + orientation orientation = B_HORIZONTAL); + + virtual void DrawMenuFieldBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, + bool popupIndicator, uint32 flags); + virtual void DrawMenuFieldBackground(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, + uint32 flags, uint32 borders); + virtual void DrawMenuFieldBackground(BView* view, BRect& rect, + const BRect& updateRect, float radius, const rgb_color& base, + bool popupIndicator, uint32 flags); + virtual void DrawMenuFieldBackground(BView* view, BRect& rect, + const BRect& updateRect, float leftTopRadius, + float rightTopRadius, float leftBottomRadius, + float rightBottomRadius, const rgb_color& base, + bool popupIndicator, uint32 flags); + virtual void DrawSplitter(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, orientation orientation, uint32 flags, + uint32 borders); + void _DrawMenuFieldBackgroundInside(BView* view, BRect& rect, + const BRect& updateRect, float leftTopRadius, + float rightTopRadius, float leftBottomRadius, + float rightBottomRadius, const rgb_color& base, + uint32 flags, uint32 borders); + void _DrawMenuFieldBackgroundOutside(BView* view, BRect& rect, + const BRect& updateRect, float leftTopRadius, + float rightTopRadius, float leftBottomRadius, + float rightBottomRadius, const rgb_color& base, + bool popupIndicator, uint32 flags); + virtual void DrawRaisedBorder(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + uint32 borders); + virtual void _DrawOuterResessedFrame(BView* view, BRect& rect, + const rgb_color& base, float contrast, float brightness, + uint32 flags, uint32 borders); + virtual void DrawScrollBarThumb(BView* view, BRect& rect, + const BRect& updateRect, const rgb_color& base, uint32 flags, + orientation orientation, uint32 knobStyle); + virtual void DrawBorder(BView* view, BRect& rect, const BRect& updateRect, + const rgb_color& base, border_style borderStyle, uint32 flags, + uint32 borders); + rgb_color _EdgeLightColor(const rgb_color& base, float contrast, + float brightness, uint32 flags); + rgb_color _EdgeShadowColor(const rgb_color& base, float contrast, + float brightness, uint32 flags); +}; + +}// bprivate + +#endif // FLAT_CONTROL_LOOK_H diff --git a/src/add-ons/control_look/FlatControlLook/FlatControlLook.rdef b/src/add-ons/control_look/FlatControlLook/FlatControlLook.rdef new file mode 100644 index 0000000000..c6ac437dbe --- /dev/null +++ b/src/add-ons/control_look/FlatControlLook/FlatControlLook.rdef @@ -0,0 +1,9 @@ +resource app_version { + major = 1, + middle = 0, + minor = 0, + variety = B_APPV_ALPHA, + internal = 0, + short_info = "Flat Control Look; Rev: 1.2 ", + long_info = "Flat-like Control Look add-on ©2020 Haiku, Inc. Author: nhtello" +}; diff --git a/src/add-ons/control_look/FlatControlLook/Jamfile b/src/add-ons/control_look/FlatControlLook/Jamfile new file mode 100644 index 0000000000..8721d29eec --- /dev/null +++ b/src/add-ons/control_look/FlatControlLook/Jamfile @@ -0,0 +1,10 @@ +SubDir HAIKU_TOP src add-ons control_look FlatControlLook ; + +UsePrivateHeaders interface ; + +AddResources FlatControlLook : FlatControlLook.rdef ; + +Addon FlatControlLook : + FlatControlLook.cpp + : be app_server [ TargetLibstdc++ ] [ TargetLibsupc++ ] +; diff --git a/src/add-ons/control_look/Jamfile b/src/add-ons/control_look/Jamfile index cfe86e919c..b22231358c 100644 --- a/src/add-ons/control_look/Jamfile +++ b/src/add-ons/control_look/Jamfile @@ -1,4 +1,5 @@ SubDir HAIKU_TOP src add-ons control_look ; SubInclude HAIKU_TOP src add-ons control_look BeControlLook ; +SubInclude HAIKU_TOP src add-ons control_look FlatControlLook ; diff --git a/src/add-ons/decorators/FlatDecorator/FlatDecorator.cpp b/src/add-ons/decorators/FlatDecorator/FlatDecorator.cpp new file mode 100644 index 0000000000..5bb0d27692 --- /dev/null +++ b/src/add-ons/decorators/FlatDecorator/FlatDecorator.cpp @@ -0,0 +1,964 @@ +/* + * Copyright 2001-2020 Haiku, Inc. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus, superstippi@gmx.de + * DarkWyrm, bpmagic@columbus.rr.com + * Ryan Leavengood, leavengood@gmail.com + * Philippe Saint-Pierre, stpere@gmail.com + * John Scipione, jscipione@gmail.com + * Ingo Weinhold, ingo_weinhold@gmx.de + * Clemens Zeidler, haiku@clemens-zeidler.de + * Joseph Groover + * Nahuel Tello + */ + + +/*! Flat decorator for dark mode theme */ + + +#include "FlatDecorator.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "BitmapDrawingEngine.h" +#include "DesktopSettings.h" +#include "DrawingEngine.h" +#include "DrawState.h" +#include "FontManager.h" +#include "PatternHandler.h" +#include "ServerBitmap.h" + + +//#define DEBUG_DECORATOR +#ifdef DEBUG_DECORATOR +# define STRACE(x) printf x +#else +# define STRACE(x) ; +#endif + + +static const float kBorderResizeLength = 22.0; + + +FlatDecorAddOn::FlatDecorAddOn(image_id id, const char* name) + : + DecorAddOn(id, name) +{ +} + + +Decorator* +FlatDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect, + Desktop* desktop) +{ + return new (std::nothrow)FlatDecorator(settings, rect, desktop); +} + + + +static inline uint8 +blend_color_value(uint8 a, uint8 b, float position) +{ + int16 delta = (int16)b - a; + int32 value = a + (int32)(position * delta); + if (value > 255) + return 255; + if (value < 0) + return 0; + + return (uint8)value; +} + + +// #pragma mark - + + +// TODO: get rid of DesktopSettings here, and introduce private accessor +// methods to the Decorator base class +FlatDecorator::FlatDecorator(DesktopSettings& settings, BRect rect, + Desktop* desktop) + : + TabDecorator(settings, rect, desktop) +{ + // TODO: If the decorator was created with a frame too small, it should + // resize itself! + + STRACE(("FlatDecorator:\n")); + STRACE(("\tFrame (%.1f,%.1f,%.1f,%.1f)\n", + rect.left, rect.top, rect.right, rect.bottom)); +} + + +FlatDecorator::~FlatDecorator() +{ + STRACE(("FlatDecorator: ~FlatDecorator()\n")); +} + + +// #pragma mark - Public methods + + +/*! Returns the frame colors for the specified decorator component. + + The meaning of the color array elements depends on the specified component. + For some components some array elements are unused. + + \param component The component for which to return the frame colors. + \param highlight The highlight set for the component. + \param colors An array of colors to be initialized by the function. +*/ +void +FlatDecorator::GetComponentColors(Component component, uint8 highlight, + ComponentColors _colors, Decorator::Tab* _tab) +{ + Decorator::Tab* tab = static_cast(_tab); + switch (component) { + case COMPONENT_TAB: + if (highlight != 0) { + _colors[COLOR_TAB_FRAME_LIGHT] + = tint_color(fFocusTabColor, 1.0); + _colors[COLOR_TAB_FRAME_DARK] + = tint_color(fFocusTabColor, 1.2); + _colors[COLOR_TAB] = tint_color(fFocusTabColor, 0.95); + _colors[COLOR_TAB_LIGHT] = fFocusTabColorLight; + _colors[COLOR_TAB_BEVEL] = fFocusTabColorBevel; + _colors[COLOR_TAB_SHADOW] = fFocusTabColorShadow; + _colors[COLOR_TAB_TEXT] = tint_color(fFocusTextColor, 0.5); + } + else if (tab && tab->buttonFocus) { + _colors[COLOR_TAB_FRAME_LIGHT] + = tint_color(fFocusTabColor, 1.0); + _colors[COLOR_TAB_FRAME_DARK] + = tint_color(fFocusTabColor, 1.2); + _colors[COLOR_TAB] = fFocusTabColor; + _colors[COLOR_TAB_LIGHT] = fFocusTabColorLight; + _colors[COLOR_TAB_BEVEL] = fFocusTabColorBevel; + _colors[COLOR_TAB_SHADOW] = fFocusTabColorShadow; + _colors[COLOR_TAB_TEXT] = fFocusTextColor; + } else { + _colors[COLOR_TAB_FRAME_LIGHT] + = tint_color(fNonFocusTabColor, 1.0); + _colors[COLOR_TAB_FRAME_DARK] + = tint_color(fNonFocusTabColor, 1.2); + _colors[COLOR_TAB] = fNonFocusTabColor; + _colors[COLOR_TAB_LIGHT] = fNonFocusTabColorLight; + _colors[COLOR_TAB_BEVEL] = fNonFocusTabColorBevel; + _colors[COLOR_TAB_SHADOW] = fNonFocusTabColorShadow; + _colors[COLOR_TAB_TEXT] = fNonFocusTextColor; + } + break; + + case COMPONENT_CLOSE_BUTTON: + case COMPONENT_ZOOM_BUTTON: + if (tab && tab->buttonFocus) { + _colors[COLOR_BUTTON] = fFocusTabColor; + _colors[COLOR_BUTTON_LIGHT] = fFocusTabColorLight; + } else { + _colors[COLOR_BUTTON] = fNonFocusTabColor; + _colors[COLOR_BUTTON_LIGHT] = fNonFocusTabColorLight; + } + break; + + case COMPONENT_TOP_BORDER: + if (tab && tab->buttonFocus) { + _colors[0] = tint_color(fFocusTabColor, 1.2); // borde exterior + _colors[1] = tint_color(fFocusTabColor, 1.0); // borde top + _colors[2] = tint_color(fFocusTabColor, 1.0); // borde top + _colors[3] = tint_color(fFocusTabColor, 1.0); // borde top + _colors[4] = tint_color(fFocusFrameColor, 1.1); // borde interior + _colors[5] = tint_color(fFocusFrameColor, 1.1); // borde menu 1 + } else { + _colors[0] = tint_color(fNonFocusTabColor, 1.2); // borde exterior + _colors[1] = tint_color(fNonFocusTabColor, B_NO_TINT); + _colors[2] = tint_color(fNonFocusTabColor, B_NO_TINT); + _colors[3] = tint_color(fNonFocusTabColor, B_NO_TINT); + _colors[4] = tint_color(fNonFocusFrameColor, 1.1); // borde interior + _colors[5] = tint_color(fNonFocusFrameColor, 1.1); // borde menu 1 + } + break; + case COMPONENT_RESIZE_CORNER: + if (tab && tab->buttonFocus) { + _colors[0] = tint_color(fFocusFrameColor, 1.25); // borde exterior + _colors[1] = tint_color(fFocusFrameColor, 1.0); // borde top + _colors[2] = tint_color(fFocusFrameColor, 1.0); // borde top + _colors[3] = tint_color(fFocusTabColor, 1.0); // borde top + _colors[4] = tint_color(fFocusFrameColor, 1.1); // borde interior + _colors[5] = tint_color(fFocusFrameColor, 1.1); // borde menu 1 + } else { + _colors[0] = tint_color(fNonFocusFrameColor, 1.25); // borde exterior + _colors[1] = tint_color(fNonFocusFrameColor, B_NO_TINT); + _colors[2] = tint_color(fNonFocusFrameColor, B_NO_TINT); + _colors[3] = tint_color(fNonFocusFrameColor, B_NO_TINT); + _colors[4] = tint_color(fNonFocusFrameColor, 1.1); // borde interior + _colors[5] = tint_color(fNonFocusFrameColor, 1.1); // borde menu 1 + } + break; + case COMPONENT_LEFT_BORDER: + case COMPONENT_RIGHT_BORDER: + if (tab && tab->buttonFocus) { + _colors[0] = tint_color(fFocusFrameColor, 1.25); // borde exterior + _colors[1] = tint_color(fFocusFrameColor, B_NO_TINT); + _colors[2] = tint_color(fFocusFrameColor, B_NO_TINT); + _colors[3] = tint_color(fFocusFrameColor, B_NO_TINT); + _colors[4] = tint_color(fFocusFrameColor, 1.05); // borde interior + _colors[5] = tint_color(fFocusFrameColor, 1.1); // borde menu 1 + _colors[6] = tint_color(fFocusTabColor, 1.2); // border tab to be part + } else { + _colors[0] = tint_color(fNonFocusFrameColor, 1.25); // borde exterior + _colors[1] = tint_color(fNonFocusFrameColor, B_NO_TINT); + _colors[2] = tint_color(fNonFocusFrameColor, B_NO_TINT); + _colors[3] = tint_color(fNonFocusFrameColor, B_NO_TINT); + _colors[4] = tint_color(fNonFocusFrameColor, 1.05); // borde interior + _colors[5] = tint_color(fNonFocusFrameColor, 1.0); // borde menu 1 + _colors[6] = tint_color(fNonFocusTabColor, 1.2); // border tab to be part + } + break; + case COMPONENT_BOTTOM_BORDER: + default: + if (tab && tab->buttonFocus) { + _colors[0] = tint_color(fFocusFrameColor, 1.25); // borde exterior + _colors[1] = tint_color(fFocusFrameColor, B_NO_TINT); + _colors[2] = tint_color(fFocusFrameColor, B_NO_TINT); + _colors[3] = tint_color(fFocusFrameColor, B_NO_TINT); + _colors[4] = tint_color(fFocusFrameColor, 1.1); // borde interior + _colors[5] = tint_color(fFocusFrameColor, 1.1); // borde menu 1 + } else { + _colors[0] = tint_color(fNonFocusFrameColor, 1.25); // borde exterior + _colors[1] = tint_color(fNonFocusFrameColor, B_NO_TINT); + _colors[2] = tint_color(fNonFocusFrameColor, B_NO_TINT); + _colors[3] = tint_color(fNonFocusFrameColor, B_NO_TINT); + _colors[4] = tint_color(fNonFocusFrameColor, 1.1); // borde interior + _colors[5] = tint_color(fNonFocusFrameColor, 1.1); // borde menu 1 + } + + // for the resize-border highlight dye everything bluish. + if (highlight == HIGHLIGHT_RESIZE_BORDER) { + for (int32 i = 0; i < 6; i++) { + _colors[i].red = std::max((int)_colors[i].red - 80, 0); + _colors[i].green = std::max((int)_colors[i].green - 80, 0); + _colors[i].blue = 255; + } + } + break; + } +} + + +void +FlatDecorator::UpdateColors(DesktopSettings& settings) +{ + TabDecorator::UpdateColors(settings); +} + + +// #pragma mark - Protected methods + + +void +FlatDecorator::_DrawFrame(BRect rect) +{ + STRACE(("_DrawFrame(%f,%f,%f,%f)\n", rect.left, rect.top, + rect.right, rect.bottom)); + + // NOTE: the DrawingEngine needs to be locked for the entire + // time for the clipping to stay valid for this decorator + + if (fTopTab->look == B_NO_BORDER_WINDOW_LOOK) + return; + + if (fBorderWidth <= 0) + return; + + // Draw the border frame + BRect r = BRect(fTopBorder.LeftTop(), fBottomBorder.RightBottom()); + switch ((int)fTopTab->look) { + case B_TITLED_WINDOW_LOOK: + case B_DOCUMENT_WINDOW_LOOK: + case B_MODAL_WINDOW_LOOK: + { + // left + if (rect.Intersects(fLeftBorder.InsetByCopy(0, -fBorderWidth))) { + ComponentColors colors; + _GetComponentColors(COMPONENT_LEFT_BORDER, colors, fTopTab); + + for (int8 i = 0; i < 5; i++) { + fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i), + BPoint(r.left + i, r.bottom - i), colors[i]); + } + // redraw line to be part of tab title + fDrawingEngine->StrokeLine(BPoint(r.left, r.top), + BPoint(r.left, r.top + 4), colors[6]); + + } + // bottom + if (rect.Intersects(fBottomBorder)) { + ComponentColors colors; + _GetComponentColors(COMPONENT_BOTTOM_BORDER, colors, fTopTab); + + for (int8 i = 0; i < 5; i++) { + fDrawingEngine->StrokeLine(BPoint(r.left + i, r.bottom - i), + BPoint(r.right - i, r.bottom - i), + colors[i]); + } + } + // right + if (rect.Intersects(fRightBorder.InsetByCopy(0, -fBorderWidth))) { + ComponentColors colors; + _GetComponentColors(COMPONENT_RIGHT_BORDER, colors, fTopTab); + + for (int8 i = 0; i < 5; i++) { + fDrawingEngine->StrokeLine(BPoint(r.right - i, r.top + i), + BPoint(r.right - i, r.bottom - i), + colors[i]); + } + // redraw line to be part of tab title + fDrawingEngine->StrokeLine(BPoint(r.right, r.top), + BPoint(r.right, r.top + 4), + colors[6]); + } + // top + if (rect.Intersects(fTopBorder)) { + ComponentColors colors; + _GetComponentColors(COMPONENT_TOP_BORDER, colors, fTopTab); + + for (int8 i = 0; i < 5; i++) { + if (i<4) + { + fDrawingEngine->StrokeLine(BPoint(r.left + 1, r.top + i), + BPoint(r.right - 1, r.top + i), tint_color(colors[i], (i*0.01+1))); + } + else + { + fDrawingEngine->StrokeLine(BPoint(r.left + 1, r.top + i), + BPoint(r.right - 1, r.top + i), tint_color(colors[3], 1.1)); + } + } + } + break; + } + + case B_FLOATING_WINDOW_LOOK: + case kLeftTitledWindowLook: + { + // top + if (rect.Intersects(fTopBorder)) { + ComponentColors colors; + _GetComponentColors(COMPONENT_TOP_BORDER, colors, fTopTab); + + for (int8 i = 0; i < 3; i++) { + fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i), + BPoint(r.right - i, r.top + i), tint_color(colors[1], 0.95)); + } + if (fTitleBarRect.IsValid() && fTopTab->look != kLeftTitledWindowLook) { + // grey along the bottom of the tab + // (overwrites "white" from frame) + fDrawingEngine->StrokeLine( + BPoint(fTitleBarRect.left + 2, + fTitleBarRect.bottom + 1), + BPoint(fTitleBarRect.right - 2, + fTitleBarRect.bottom + 1), colors[2]); + } + } + // left + if (rect.Intersects(fLeftBorder.InsetByCopy(0, -fBorderWidth))) { + ComponentColors colors; + _GetComponentColors(COMPONENT_LEFT_BORDER, colors, fTopTab); + + for (int8 i = 0; i < 3; i++) { + fDrawingEngine->StrokeLine(BPoint(r.left + i, r.top + i), + BPoint(r.left + i, r.bottom - i), colors[i * 2]); + } + if (fTopTab->look == kLeftTitledWindowLook + && fTitleBarRect.IsValid()) { + // grey along the right side of the tab + // (overwrites "white" from frame) + fDrawingEngine->StrokeLine( + BPoint(fTitleBarRect.right + 1, + fTitleBarRect.top + 2), + BPoint(fTitleBarRect.right + 1, + fTitleBarRect.bottom - 2), colors[2]); + } + } + // bottom + if (rect.Intersects(fBottomBorder)) { + ComponentColors colors; + _GetComponentColors(COMPONENT_BOTTOM_BORDER, colors, fTopTab); + + for (int8 i = 0; i < 3; i++) { + fDrawingEngine->StrokeLine(BPoint(r.left + i, r.bottom - i), + BPoint(r.right - i, r.bottom - i), + colors[(2 - i) == 2 ? 5 : (2 - i) * 2]); + } + } + // right + if (rect.Intersects(fRightBorder.InsetByCopy(0, -fBorderWidth))) { + ComponentColors colors; + _GetComponentColors(COMPONENT_RIGHT_BORDER, colors, fTopTab); + + for (int8 i = 0; i < 3; i++) { + fDrawingEngine->StrokeLine(BPoint(r.right - i, r.top + i), + BPoint(r.right - i, r.bottom - i), + colors[(2 - i) == 2 ? 5 : (2 - i) * 2]); + } + } + break; + } + + case B_BORDERED_WINDOW_LOOK: + { + // TODO: Draw the borders individually! + ComponentColors colors; + _GetComponentColors(COMPONENT_LEFT_BORDER, colors, fTopTab); + + fDrawingEngine->StrokeRect(r, colors[5]); + break; + } + + default: + // don't draw a border frame + break; + } + + // Draw the resize knob if we're supposed to + if (!(fTopTab->flags & B_NOT_RESIZABLE)) { + r = fResizeRect; + + ComponentColors colors; + _GetComponentColors(COMPONENT_RESIZE_CORNER, colors, fTopTab); + + switch ((int)fTopTab->look) { + case B_DOCUMENT_WINDOW_LOOK: + { + if (!rect.Intersects(r)) + break; + + float x = r.right - 3; + float y = r.bottom - 3; + + BRect bg(x - 15, y - 15, x, y); + + BGradientLinear gradient; + gradient.SetStart(bg.LeftTop()); + gradient.SetEnd(bg.RightBottom()); + gradient.AddColor(tint_color(colors[1], 1.05), 0); + gradient.AddColor(tint_color(colors[1], 1.0), 255); + + fDrawingEngine->FillRect(bg, gradient); + + fDrawingEngine->StrokeLine(BPoint(x - 15, y - 15), + BPoint(x - 15, y - 1), colors[4]); + fDrawingEngine->StrokeLine(BPoint(x - 15, y - 15), + BPoint(x - 1, y - 15), colors[4]); + + if (fTopTab && !IsFocus(fTopTab)) + break; + + for (int8 i = 1; i <= 4; i++) { + for (int8 j = 1; j <= i; j++) { + BPoint pt1(x - (3 * j) + 1, y - (3 * (5 - i)) + 1); + BPoint pt2(x - (3 * j) + 2, y - (3 * (5 - i)) + 2); + fDrawingEngine->StrokePoint(pt1, tint_color(colors[1], 1.5)); + fDrawingEngine->StrokePoint(pt2, tint_color(colors[1], 0.75)); + } + } + break; + } + + case B_TITLED_WINDOW_LOOK: + case B_FLOATING_WINDOW_LOOK: + case B_MODAL_WINDOW_LOOK: + case kLeftTitledWindowLook: + { + if (!rect.Intersects(BRect(fRightBorder.right - kBorderResizeLength, + fBottomBorder.bottom - kBorderResizeLength, fRightBorder.right - 1, + fBottomBorder.bottom - 1))) + break; + + fDrawingEngine->StrokeLine( + BPoint(fRightBorder.left, fBottomBorder.bottom - kBorderResizeLength), + BPoint(fRightBorder.right - 1, fBottomBorder.bottom - kBorderResizeLength), + tint_color(colors[1], 1.2)); + fDrawingEngine->StrokeLine( + BPoint(fRightBorder.right - kBorderResizeLength, fBottomBorder.top), + BPoint(fRightBorder.right - kBorderResizeLength, fBottomBorder.bottom - 1), + tint_color(colors[1], 1.2)); + + // Try to draw line in yellow to the resize place + for (int8 i = 1; i < 4; i++) { + fDrawingEngine->StrokeLine( + BPoint(fRightBorder.left+i, fBottomBorder.bottom - kBorderResizeLength + 1), + BPoint(fRightBorder.left+i, fBottomBorder.bottom - 1), + tint_color(colors[3], (i * 0.06) + 1)); + } + int rez[] = {4,3,2,1}; + for (int8 i = 1; i < 4; i++) { + fDrawingEngine->StrokeLine( + BPoint(fRightBorder.right - kBorderResizeLength + 1, fBottomBorder.bottom - i), + BPoint(fRightBorder.right - i, fBottomBorder.bottom - i ), + tint_color(colors[3], (rez[i] * 0.06) + 1)); + } + + break; + } + + default: + // don't draw resize corner + break; + } + } +} + + +/*! \brief Actually draws the tab + + This function is called when the tab itself needs drawn. Other items, + like the window title or buttons, should not be drawn here. + + \param tab The \a tab to update. + \param rect The area of the \a tab to update. +*/ +void +FlatDecorator::_DrawTab(Decorator::Tab* tab, BRect invalid) +{ + STRACE(("_DrawTab(%.1f,%.1f,%.1f,%.1f)\n", + invalid.left, invalid.top, invalid.right, invalid.bottom)); + const BRect& tabRect = tab->tabRect; + // If a window has a tab, this will draw it and any buttons which are + // in it. + if (!tabRect.IsValid() || !invalid.Intersects(tabRect)) + return; + + ComponentColors colors; + _GetComponentColors(COMPONENT_TAB, colors, tab); + + if (tab && tab->buttonFocus) { + // outer frame + fDrawingEngine->StrokeLine(tabRect.LeftTop(), tabRect.LeftBottom(), + colors[COLOR_TAB_FRAME_DARK]); + fDrawingEngine->StrokeLine(tabRect.LeftTop(), tabRect.RightTop(), + colors[COLOR_TAB_FRAME_DARK]); + if (tab->look != kLeftTitledWindowLook) { + fDrawingEngine->StrokeLine(tabRect.RightTop(), tabRect.RightBottom(), + colors[COLOR_TAB_FRAME_DARK]); + } else { + fDrawingEngine->StrokeLine(tabRect.LeftBottom(), + tabRect.RightBottom(), fFocusFrameColor); + } + } else { + // outer frame + fDrawingEngine->StrokeLine(tabRect.LeftTop(), tabRect.LeftBottom(), + colors[COLOR_TAB_FRAME_DARK]); + fDrawingEngine->StrokeLine(tabRect.LeftTop(), tabRect.RightTop(), + colors[COLOR_TAB_FRAME_DARK]); + if (tab->look != kLeftTitledWindowLook) { + fDrawingEngine->StrokeLine(tabRect.RightTop(), tabRect.RightBottom(), + colors[COLOR_TAB_FRAME_DARK]); + } else { + fDrawingEngine->StrokeLine(tabRect.LeftBottom(), + tabRect.RightBottom(), fFocusFrameColor); + } + } + + float tabBotton = tabRect.bottom; + if (fTopTab != tab) + tabBotton -= 1; + + // bevel + fDrawingEngine->StrokeLine(BPoint(tabRect.left + 1, tabRect.top + 1), + BPoint(tabRect.left + 1, + tabBotton - (tab->look == kLeftTitledWindowLook ? 1 : 0)), + colors[COLOR_TAB]); + fDrawingEngine->StrokeLine(BPoint(tabRect.left + 1, tabRect.top + 1), + BPoint(tabRect.right - (tab->look == kLeftTitledWindowLook ? 0 : 1), + tabRect.top + 1), + tint_color(colors[COLOR_TAB], 0.9)); + + if (tab->look != kLeftTitledWindowLook) { + fDrawingEngine->StrokeLine(BPoint(tabRect.right - 1, tabRect.top + 2), + BPoint(tabRect.right - 1, tabBotton), + colors[COLOR_TAB]); + } else { + fDrawingEngine->StrokeLine( + BPoint(tabRect.left + 2, tabRect.bottom - 1), + BPoint(tabRect.right, tabRect.bottom - 1), + colors[COLOR_TAB]); + } + + // fill + BGradientLinear gradient; + gradient.SetStart(tabRect.LeftTop()); + if (tab && tab->buttonFocus) { + gradient.AddColor(tint_color(colors[COLOR_TAB], 0.6), 0); + gradient.AddColor(tint_color(colors[COLOR_TAB], 1.0), 200); + } else { + gradient.AddColor(tint_color(colors[COLOR_TAB], 0.9), 0); + gradient.AddColor(tint_color(colors[COLOR_TAB], 1.0), 150); + } + + if (tab->look != kLeftTitledWindowLook) { + gradient.SetEnd(tabRect.LeftBottom()); + fDrawingEngine->FillRect(BRect(tabRect.left + 2, tabRect.top + 2, + tabRect.right - 2, tabBotton), gradient); + } else { + gradient.SetEnd(tabRect.RightTop()); + fDrawingEngine->FillRect(BRect(tabRect.left + 2, tabRect.top + 2, + tabRect.right, tabRect.bottom - 2), gradient); + } + + _DrawTitle(tab, tabRect); + + _DrawButtons(tab, invalid); +} + + +/*! \brief Actually draws the title + + The main tasks for this function are to ensure that the decorator draws + the title only in its own area and drawing the title itself. + Using B_OP_COPY for drawing the title is recommended because of the marked + performance hit of the other drawing modes, but it is not a requirement. + + \param tab The \a tab to update. + \param rect area of the title to update. +*/ +void +FlatDecorator::_DrawTitle(Decorator::Tab* _tab, BRect rect) +{ + STRACE(("_DrawTitle(%f,%f,%f,%f)\n", rect.left, rect.top, rect.right, + rect.bottom)); + + Decorator::Tab* tab = static_cast(_tab); + + const BRect& tabRect = tab->tabRect; + const BRect& closeRect = tab->closeRect; + const BRect& zoomRect = tab->zoomRect; + + ComponentColors colors; + _GetComponentColors(COMPONENT_TAB, colors, tab); + + fDrawingEngine->SetDrawingMode(B_OP_OVER); + fDrawingEngine->SetHighColor(colors[COLOR_TAB_TEXT]); + fDrawingEngine->SetFont(fDrawState.Font()); + + // figure out position of text + font_height fontHeight; + fDrawState.Font().GetHeight(fontHeight); + + BPoint titlePos; + if (tab->look != kLeftTitledWindowLook) { + titlePos.x = closeRect.IsValid() ? closeRect.right + tab->textOffset + : tabRect.left + tab->textOffset; + titlePos.y = floorf(((tabRect.top + 2.0) + tabRect.bottom + + fontHeight.ascent + fontHeight.descent) / 2.0 + - fontHeight.descent + 0.5); + } else { + titlePos.x = floorf(((tabRect.left + 2.0) + tabRect.right + + fontHeight.ascent + fontHeight.descent) / 2.0 + - fontHeight.descent + 0.5); + titlePos.y = zoomRect.IsValid() ? zoomRect.top - tab->textOffset + : tabRect.bottom - tab->textOffset; + } + + fDrawingEngine->DrawString(tab->truncatedTitle, tab->truncatedTitleLength, + titlePos); + + fDrawingEngine->SetDrawingMode(B_OP_COPY); +} + + +/*! \brief Actually draws the close button + + Unless a subclass has a particularly large button, it is probably + unnecessary to check the update rectangle. + + \param _tab The \a tab to update. + \param direct Draw without double buffering. + \param rect The area of the button to update. +*/ +void +FlatDecorator::_DrawClose(Decorator::Tab* _tab, bool direct, BRect rect) +{ + STRACE(("_DrawClose(%f,%f,%f,%f)\n", rect.left, rect.top, rect.right, + rect.bottom)); + + Decorator::Tab* tab = static_cast(_tab); + + int32 index = (tab->buttonFocus ? 0 : 1) + (tab->closePressed ? 0 : 2); + ServerBitmap* bitmap = tab->closeBitmaps[index]; + if (bitmap == NULL) { + bitmap = _GetBitmapForButton(tab, COMPONENT_CLOSE_BUTTON, + tab->closePressed, rect.IntegerWidth(), rect.IntegerHeight()); + tab->closeBitmaps[index] = bitmap; + } + + _DrawButtonBitmap(bitmap, direct, rect); +} + + +/*! \brief Actually draws the zoom button + + Unless a subclass has a particularly large button, it is probably + unnecessary to check the update rectangle. + + \param _tab The \a tab to update. + \param direct Draw without double buffering. + \param rect The area of the button to update. +*/ +void +FlatDecorator::_DrawZoom(Decorator::Tab* _tab, bool direct, BRect rect) +{ + STRACE(("_DrawZoom(%f,%f,%f,%f)\n", rect.left, rect.top, rect.right, + rect.bottom)); + + if (rect.IntegerWidth() < 1) + return; + + Decorator::Tab* tab = static_cast(_tab); + int32 index = (tab->buttonFocus ? 0 : 1) + (tab->zoomPressed ? 0 : 2); + ServerBitmap* bitmap = tab->zoomBitmaps[index]; + if (bitmap == NULL) { + bitmap = _GetBitmapForButton(tab, COMPONENT_ZOOM_BUTTON, + tab->zoomPressed, rect.IntegerWidth(), rect.IntegerHeight()); + tab->zoomBitmaps[index] = bitmap; + } + + _DrawButtonBitmap(bitmap, direct, rect); +} + + +void +FlatDecorator::_DrawMinimize(Decorator::Tab* tab, bool direct, BRect rect) +{ + // This decorator doesn't have this button +} + + +// #pragma mark - Private methods + + +void +FlatDecorator::_DrawButtonBitmap(ServerBitmap* bitmap, bool direct, + BRect rect) +{ + if (bitmap == NULL) + return; + + bool copyToFrontEnabled = fDrawingEngine->CopyToFrontEnabled(); + fDrawingEngine->SetCopyToFrontEnabled(direct); + drawing_mode oldMode; + fDrawingEngine->SetDrawingMode(B_OP_OVER, oldMode); + fDrawingEngine->DrawBitmap(bitmap, rect.OffsetToCopy(0, 0), rect); + fDrawingEngine->SetDrawingMode(oldMode); + fDrawingEngine->SetCopyToFrontEnabled(copyToFrontEnabled); +} + + +/*! \brief Draws a framed rectangle with a gradient. + \param engine The drawing engine to use. + \param rect The rectangular area to draw in. + \param down The rectangle should be drawn recessed or not. + \param colors A button color array of the colors to be used. +*/ +void +FlatDecorator::_DrawBlendedRect(DrawingEngine* engine, const BRect rect, + bool down, const ComponentColors& colors) +{ + engine->FillRect(rect, B_TRANSPARENT_COLOR); + + // figure out which colors to use + rgb_color startColor, endColor; + if (down) { + startColor = tint_color(colors[COLOR_BUTTON], 1.0); + endColor = tint_color(colors[COLOR_BUTTON], 0.9); + } else { + startColor = tint_color(colors[COLOR_BUTTON], 0.95); + endColor = tint_color(colors[COLOR_BUTTON], 0.5); + } + + // fill + BRect fillRect(rect.InsetByCopy(1.0f, 1.0f)); + + BGradientLinear gradient; + gradient.SetStart(fillRect.LeftBottom()); + gradient.SetEnd(fillRect.LeftTop()); + gradient.AddColor(startColor, 0); + gradient.AddColor(endColor, 250); + + engine->FillRect(fillRect, gradient); + + // outline + engine->StrokeRect(rect, tint_color(colors[COLOR_BUTTON], 1.25)); + +} + + +ServerBitmap* +FlatDecorator::_GetBitmapForButton(Decorator::Tab* tab, Component item, + bool down, int32 width, int32 height) +{ + // TODO: the list of shared bitmaps is never freed + struct decorator_bitmap { + Component item; + bool down; + int32 width; + int32 height; + rgb_color baseColor; + rgb_color lightColor; + UtilityBitmap* bitmap; + decorator_bitmap* next; + }; + + static BLocker sBitmapListLock("decorator lock", true); + static decorator_bitmap* sBitmapList = NULL; + + ComponentColors colors; + _GetComponentColors(item, colors, tab); + + BAutolock locker(sBitmapListLock); + + // search our list for a matching bitmap + // TODO: use a hash map instead? + decorator_bitmap* current = sBitmapList; + while (current) { + if (current->item == item && current->down == down + && current->width == width && current->height == height + && current->baseColor == colors[COLOR_BUTTON] + && current->lightColor == colors[COLOR_BUTTON_LIGHT]) { + return current->bitmap; + } + + current = current->next; + } + + static BitmapDrawingEngine* sBitmapDrawingEngine = NULL; + + // didn't find any bitmap, create a new one + if (sBitmapDrawingEngine == NULL) + sBitmapDrawingEngine = new(std::nothrow) BitmapDrawingEngine(); + if (sBitmapDrawingEngine == NULL + || sBitmapDrawingEngine->SetSize(width, height) != B_OK) + return NULL; + + BRect rect(0, 0, width - 1, height - 1); + + STRACE(("FlatDecorator creating bitmap for %s %s at size %ldx%ld\n", + item == COMPONENT_CLOSE_BUTTON ? "close" : "zoom", + down ? "down" : "up", width, height)); + switch (item) { + case COMPONENT_CLOSE_BUTTON: + if (tab && tab->buttonFocus) + _DrawBlendedRect(sBitmapDrawingEngine, rect, down, colors); + else + _DrawBlendedRect(sBitmapDrawingEngine, rect, true, colors); + break; + + case COMPONENT_ZOOM_BUTTON: + { + sBitmapDrawingEngine->FillRect(rect, B_TRANSPARENT_COLOR); + // init the background + + float inset = floorf(width / 4.0); + BRect zoomRect(rect); + zoomRect.left += inset; + zoomRect.top += inset; + if (tab && tab->buttonFocus) + _DrawBlendedRect(sBitmapDrawingEngine, zoomRect, down, colors); + else + _DrawBlendedRect(sBitmapDrawingEngine, zoomRect, true, colors); + + inset = floorf(width / 2.1); + zoomRect = rect; + zoomRect.right -= inset; + zoomRect.bottom -= inset; + if (tab && tab->buttonFocus) + _DrawBlendedRect(sBitmapDrawingEngine, zoomRect, down, colors); + else + _DrawBlendedRect(sBitmapDrawingEngine, zoomRect, true, colors); + break; + } + + default: + break; + } + + UtilityBitmap* bitmap = sBitmapDrawingEngine->ExportToBitmap(width, height, + B_RGB32); + if (bitmap == NULL) + return NULL; + + // bitmap ready, put it into the list + decorator_bitmap* entry = new(std::nothrow) decorator_bitmap; + if (entry == NULL) { + delete bitmap; + return NULL; + } + + entry->item = item; + entry->down = down; + entry->width = width; + entry->height = height; + entry->bitmap = bitmap; + entry->baseColor = colors[COLOR_BUTTON]; + entry->lightColor = colors[COLOR_BUTTON_LIGHT]; + entry->next = sBitmapList; + sBitmapList = entry; + + return bitmap; +} + + +void +FlatDecorator::_GetComponentColors(Component component, + ComponentColors _colors, Decorator::Tab* tab) +{ + // get the highlight for our component + Region region = REGION_NONE; + switch (component) { + case COMPONENT_TAB: + region = REGION_TAB; + break; + case COMPONENT_CLOSE_BUTTON: + region = REGION_CLOSE_BUTTON; + break; + case COMPONENT_ZOOM_BUTTON: + region = REGION_ZOOM_BUTTON; + break; + case COMPONENT_LEFT_BORDER: + region = REGION_LEFT_BORDER; + break; + case COMPONENT_RIGHT_BORDER: + region = REGION_RIGHT_BORDER; + break; + case COMPONENT_TOP_BORDER: + region = REGION_TOP_BORDER; + break; + case COMPONENT_BOTTOM_BORDER: + region = REGION_BOTTOM_BORDER; + break; + case COMPONENT_RESIZE_CORNER: + region = REGION_RIGHT_BOTTOM_CORNER; + break; + } + + return GetComponentColors(component, RegionHighlight(region), _colors, tab); +} + + +extern "C" DecorAddOn* (instantiate_decor_addon)(image_id id, const char* name) +{ + return new (std::nothrow)FlatDecorAddOn(id, name); +} diff --git a/src/add-ons/decorators/FlatDecorator/FlatDecorator.h b/src/add-ons/decorators/FlatDecorator/FlatDecorator.h new file mode 100644 index 0000000000..999ede44de --- /dev/null +++ b/src/add-ons/decorators/FlatDecorator/FlatDecorator.h @@ -0,0 +1,75 @@ +/* + * Copyright 2001-2015 Haiku, Inc. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus, superstippi@gmx.de + * DarkWyrm, bpmagic@columbus.rr.com + * Ryan Leavengood, leavengood@gmail.com + * Philippe Saint-Pierre, stpere@gmail.com + * John Scipione, jscipione@gmail.com + * Ingo Weinhold, ingo_weinhold@gmx.de + * Clemens Zeidler, haiku@clemens-zeidler.de + * Joseph Groover + */ +#ifndef FLAT_DECORATOR_H +#define FLAT_DECORATOR_H + + +#include "TabDecorator.h" +#include "DecorManager.h" + + +class Desktop; +class ServerBitmap; + +class FlatDecorAddOn : public DecorAddOn { +public: + FlatDecorAddOn(image_id id, const char* name); + +protected: + virtual Decorator* _AllocateDecorator(DesktopSettings& settings, + BRect rect, Desktop* desktop); +}; + +class FlatDecorator: public TabDecorator { +public: + FlatDecorator(DesktopSettings& settings, + BRect frame, Desktop* desktop); + virtual ~FlatDecorator(); + + virtual void GetComponentColors(Component component, + uint8 highlight, ComponentColors _colors, + Decorator::Tab* tab = NULL); + + virtual void UpdateColors(DesktopSettings& settings); + +protected: + virtual void _DrawFrame(BRect rect); + + virtual void _DrawTab(Decorator::Tab* tab, BRect r); + virtual void _DrawTitle(Decorator::Tab* tab, BRect r); + virtual void _DrawClose(Decorator::Tab* tab, bool direct, + BRect rect); + virtual void _DrawZoom(Decorator::Tab* tab, bool direct, + BRect rect); + virtual void _DrawMinimize(Decorator::Tab* tab, bool direct, + BRect rect); + +private: + void _DrawButtonBitmap(ServerBitmap* bitmap, + bool direct, BRect rect); + void _DrawBlendedRect(DrawingEngine *engine, + const BRect rect, bool down, + const ComponentColors& colors); + ServerBitmap* _GetBitmapForButton(Decorator::Tab* tab, + Component item, bool down, int32 width, + int32 height); + + void _GetComponentColors(Component component, + ComponentColors _colors, + Decorator::Tab* tab = NULL); +}; + + +#endif // FLAT_DECORATOR_H diff --git a/src/add-ons/decorators/FlatDecorator/Jamfile b/src/add-ons/decorators/FlatDecorator/Jamfile new file mode 100644 index 0000000000..cc2364bbad --- /dev/null +++ b/src/add-ons/decorators/FlatDecorator/Jamfile @@ -0,0 +1,22 @@ +SubDir HAIKU_TOP src add-ons decorators FlatDecorator ; + +UseBuildFeatureHeaders freetype ; +UseHeaders [ FDirName $(HAIKU_TOP) src servers app ] ; +UseHeaders [ FDirName $(HAIKU_TOP) src servers app stackandtile ] ; +UseHeaders [ FDirName $(HAIKU_TOP) src servers app decorator ] ; +UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing ] ; +UseHeaders [ FDirName $(HAIKU_TOP) src servers app drawing Painter ] ; +UseHeaders [ FDirName $(HAIKU_TOP) src servers app font ] ; +UsePrivateHeaders app shared interface graphics ; +UseLibraryHeaders agg ; +UsePrivateHeaders kernel ; + +AddResources FlatDecorator : resources.rdef ; + +Includes [ FGristFiles FlatDecorator.cpp ] + : [ BuildFeatureAttribute freetype : headers ] ; + +Addon FlatDecorator : + FlatDecorator.cpp + : be app_server [ TargetLibstdc++ ] [ TargetLibsupc++ ] +; diff --git a/src/add-ons/decorators/FlatDecorator/resources.rdef b/src/add-ons/decorators/FlatDecorator/resources.rdef new file mode 100644 index 0000000000..03d9de0600 --- /dev/null +++ b/src/add-ons/decorators/FlatDecorator/resources.rdef @@ -0,0 +1,10 @@ +resource("be:decor:info") message('deco') { + "name" = "FlatDecorator", + "authors" = "Nhtello", + "short_descr" = "FlatDecorator for Haiku v1.3", + "long_descr" = "FlatDecorator: best if you use it with FlatControlLook", + "lic_url" = "", + "lic_name" = "MIT", + "support_url" = "http://www.haiku-os.org/", + float "version" = 1.3 +}; diff --git a/src/add-ons/decorators/Jamfile b/src/add-ons/decorators/Jamfile index c6e86651da..433718b5c5 100644 --- a/src/add-ons/decorators/Jamfile +++ b/src/add-ons/decorators/Jamfile @@ -1,5 +1,6 @@ SubDir HAIKU_TOP src add-ons decorators ; SubInclude HAIKU_TOP src add-ons decorators BeDecorator ; +SubInclude HAIKU_TOP src add-ons decorators FlatDecorator ; SubInclude HAIKU_TOP src add-ons decorators MacDecorator ; SubInclude HAIKU_TOP src add-ons decorators WinDecorator ; diff --git a/src/data/package_infos/generic/haiku_extras b/src/data/package_infos/generic/haiku_extras index 9ec089e275..40166e8025 100644 --- a/src/data/package_infos/generic/haiku_extras +++ b/src/data/package_infos/generic/haiku_extras @@ -2,8 +2,8 @@ name haiku_extras version %HAIKU_VERSION% architecture %HAIKU_PACKAGING_ARCH% summary "Haiku extra files" -description "Miscellaneous files and applications for Haiku, usually not -needed on standard installations." +description "A delightfully hand-curated set of oddities and tidbits to +enhance your usage of Haiku." packager "The Haiku build system" vendor "Haiku Project"