2022-06-11 13:00:24 -05:00
|
|
|
/*
|
|
|
|
* Copyright 2022, Jaidyn Levesque <jadedctrl@teknik.io>
|
|
|
|
* All rights reserved. Distributed under the terms of the MIT license.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ImageControlLook.h"
|
|
|
|
|
2022-06-11 21:26:46 -05:00
|
|
|
#include <cstdio>
|
|
|
|
|
|
|
|
#include <TranslationUtils.h>
|
|
|
|
|
2022-06-11 13:00:24 -05:00
|
|
|
|
|
|
|
ImageControlLook::ImageControlLook(image_id id)
|
|
|
|
:
|
|
|
|
HaikuControlLook()
|
|
|
|
{
|
2022-06-11 21:26:46 -05:00
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
fButton[i].fill(NULL);
|
2022-06-12 12:08:29 -05:00
|
|
|
fCheckBox_Checked.fill(NULL);
|
|
|
|
fCheckBox_Unchecked.fill(NULL);
|
2022-06-12 12:49:11 -05:00
|
|
|
fSliderThumb.fill(NULL);
|
|
|
|
fSliderTriangle.fill(NULL);
|
2022-06-12 12:08:29 -05:00
|
|
|
|
2022-06-12 19:33:49 -05:00
|
|
|
fImageRoot = BPath("/boot/home/Desktop/projects/haiku/ImageControlLook/data/ImageThemes/Akva/");
|
2022-06-11 13:00:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ImageControlLook::~ImageControlLook()
|
|
|
|
{
|
2022-06-11 21:26:46 -05:00
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
for (int j = 0; j < 6; j++)
|
|
|
|
delete fButton[i][j];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// No need to draw button frames (since the button images should include them)
|
|
|
|
void
|
|
|
|
ImageControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect,
|
|
|
|
const rgb_color& base, const rgb_color& background, uint32 flags, uint32 borders)
|
|
|
|
{
|
2022-06-12 10:15:17 -05:00
|
|
|
if (_Image("Button", ICL_MIDDLE, ICL_NORMAL) == NULL)
|
2022-06-11 21:26:46 -05:00
|
|
|
HaikuControlLook::DrawButtonFrame(view, rect, updateRect, base, background, flags, borders);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ImageControlLook::DrawButtonFrame(BView* view, BRect& rect, const BRect& updateRect, float radius,
|
|
|
|
const rgb_color& base, const rgb_color& background, uint32 flags, uint32 borders)
|
|
|
|
{
|
2022-06-12 10:15:17 -05:00
|
|
|
if (_Image("Button", ICL_MIDDLE, ICL_NORMAL) == NULL)
|
2022-06-11 21:26:46 -05:00
|
|
|
HaikuControlLook::DrawButtonFrame(view, rect, updateRect, radius, base, background, flags,
|
|
|
|
borders);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ImageControlLook::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)
|
|
|
|
{
|
2022-06-12 10:15:17 -05:00
|
|
|
if (_Image("Button", ICL_MIDDLE, ICL_NORMAL) == NULL)
|
2022-06-11 21:26:46 -05:00
|
|
|
HaikuControlLook::DrawButtonFrame(view, rect, updateRect, leftTopRadius, rightTopRadius,
|
|
|
|
leftBottomRadius, rightBottomRadius, base, background, flags, borders);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ImageControlLook::DrawButtonBackground(BView* view, BRect& rect, const BRect& updateRect,
|
|
|
|
const rgb_color& base, uint32 flags, uint32 borders, orientation orientation)
|
|
|
|
{
|
2022-06-12 12:49:11 -05:00
|
|
|
if (!_DrawTiledImage("Button", _FlagsToState(flags), view, rect, updateRect, orientation))
|
2022-06-11 21:26:46 -05:00
|
|
|
HaikuControlLook::DrawButtonBackground(view, rect, updateRect, base, flags, borders,
|
|
|
|
orientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ImageControlLook::DrawButtonBackground(BView* view, BRect& rect, const BRect& updateRect,
|
|
|
|
float radius, const rgb_color& base, uint32 flags, uint32 borders, orientation orientation)
|
|
|
|
{
|
2022-06-12 12:49:11 -05:00
|
|
|
if (!_DrawTiledImage("Button", _FlagsToState(flags), view, rect, updateRect, orientation))
|
2022-06-11 21:26:46 -05:00
|
|
|
HaikuControlLook::DrawButtonBackground(view, rect, updateRect, radius, base, flags, borders,
|
|
|
|
orientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ImageControlLook::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)
|
|
|
|
{
|
2022-06-12 12:49:11 -05:00
|
|
|
if (!_DrawTiledImage("Button", _FlagsToState(flags), view, rect, updateRect, orientation))
|
2022-06-11 21:26:46 -05:00
|
|
|
HaikuControlLook::DrawButtonBackground(view, rect, updateRect, leftTopRadius,
|
|
|
|
rightTopRadius,leftBottomRadius, rightBottomRadius, base, flags, borders, orientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-06-12 12:08:29 -05:00
|
|
|
void
|
|
|
|
ImageControlLook::DrawCheckBox(BView* view, BRect& rect, const BRect& updateRect,
|
|
|
|
const rgb_color& base, uint32 flags)
|
|
|
|
{
|
2022-06-12 12:49:11 -05:00
|
|
|
bool drawn = false;
|
2022-06-12 12:08:29 -05:00
|
|
|
if (((BControl*)view)->Value() == B_CONTROL_ON)
|
2022-06-12 12:49:11 -05:00
|
|
|
drawn = _DrawImage("CheckBox-Checked", _FlagsToState(flags & ~B_ACTIVATED), view, rect);
|
2022-06-12 12:08:29 -05:00
|
|
|
else
|
2022-06-12 12:49:11 -05:00
|
|
|
drawn = _DrawImage("CheckBox-Unchecked", _FlagsToState(flags), view, rect);
|
2022-06-12 12:08:29 -05:00
|
|
|
|
2022-06-12 12:49:11 -05:00
|
|
|
if (!drawn)
|
2022-06-12 12:08:29 -05:00
|
|
|
HaikuControlLook::DrawCheckBox(view, rect, updateRect, base, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-06-12 12:49:11 -05:00
|
|
|
void
|
|
|
|
ImageControlLook::DrawSliderThumb(BView* view, BRect& rect, const BRect& updateRect,
|
|
|
|
const rgb_color& base, uint32 flags, orientation orientation)
|
2022-06-11 21:26:46 -05:00
|
|
|
{
|
2022-06-12 12:49:11 -05:00
|
|
|
if (!_DrawImage("SliderThumb", _FlagsToState(flags), view, rect, orientation))
|
|
|
|
HaikuControlLook::DrawSliderThumb(view, rect, updateRect, base, flags, orientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ImageControlLook::DrawSliderTriangle(BView* view, BRect& rect, const BRect& updateRect,
|
|
|
|
const rgb_color& base, uint32 flags, orientation orientation)
|
|
|
|
{
|
|
|
|
if (!_DrawImage("SliderTriangle", _FlagsToState(flags), view, rect, orientation))
|
|
|
|
HaikuControlLook::DrawSliderTriangle(view, rect, updateRect, base, flags, orientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
ImageControlLook::DrawSliderTriangle(BView* view, BRect& rect, const BRect& updateRect,
|
|
|
|
const rgb_color& base, const rgb_color& fill, uint32 flags, orientation orientation)
|
|
|
|
{
|
|
|
|
if (!_DrawImage("SliderTriangle", _FlagsToState(flags), view, rect, orientation))
|
|
|
|
HaikuControlLook::DrawSliderTriangle(view, rect, updateRect, base, fill, flags,
|
|
|
|
orientation);
|
2022-06-12 10:15:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2022-06-12 12:49:11 -05:00
|
|
|
ImageControlLook::_DrawImage(const char* type, uint32 state, BView* view, BRect rect,
|
|
|
|
orientation orientation)
|
2022-06-12 10:15:17 -05:00
|
|
|
{
|
2022-06-12 12:49:11 -05:00
|
|
|
BBitmap* image = _Image(type, state);
|
|
|
|
if (image != NULL && orientation == B_HORIZONTAL) {
|
|
|
|
view->SetDrawingMode(B_OP_ALPHA);
|
|
|
|
view->DrawBitmap(image, rect);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
ImageControlLook::_DrawTiledImage(const char* type, uint32 state, BView* view, BRect rect,
|
|
|
|
BRect updateRect, orientation orientation)
|
|
|
|
{
|
|
|
|
BBitmap* tile = _Image(type, state, ICL_MIDDLE);
|
|
|
|
BBitmap* left = _Image(type, state, ICL_LEFT);
|
|
|
|
BBitmap* right = _Image(type, state, ICL_RIGHT);
|
2022-06-11 21:26:46 -05:00
|
|
|
|
|
|
|
if (orientation == B_VERTICAL || tile == NULL)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
float minX = 0;
|
|
|
|
float maxX = rect.Width();
|
|
|
|
if (left != NULL)
|
|
|
|
minX = left->Bounds().Width();
|
|
|
|
if (right != NULL)
|
|
|
|
maxX = rect.Width() - right->Bounds().Width();
|
|
|
|
|
|
|
|
float heightRatio = rect.Height() / tile->Bounds().Height();
|
|
|
|
float sliceWidth = heightRatio * tile->Bounds().Width();
|
|
|
|
|
|
|
|
view->SetDrawingMode(B_OP_ALPHA);
|
|
|
|
|
|
|
|
BRect tileRect;
|
|
|
|
tileRect.top = 0;
|
|
|
|
tileRect.bottom = rect.Height();
|
|
|
|
for (float left = minX; left + sliceWidth < maxX; left += sliceWidth) {
|
|
|
|
tileRect.left = left;
|
|
|
|
tileRect.right = left + sliceWidth;
|
2022-06-12 12:49:11 -05:00
|
|
|
if (tileRect.Intersects(updateRect))
|
|
|
|
view->DrawBitmap(tile, tileRect);
|
2022-06-11 21:26:46 -05:00
|
|
|
}
|
|
|
|
tileRect.right = maxX;
|
|
|
|
tileRect.left = maxX - sliceWidth;
|
2022-06-12 12:49:11 -05:00
|
|
|
if (tileRect.Intersects(updateRect))
|
|
|
|
view->DrawBitmap(tile, tileRect);
|
2022-06-11 21:26:46 -05:00
|
|
|
|
|
|
|
BRect sideRect(0, 0, minX, rect.Height());
|
2022-06-12 12:49:11 -05:00
|
|
|
if (left != NULL && sideRect.Intersects(updateRect))
|
2022-06-11 21:26:46 -05:00
|
|
|
view->DrawBitmap(left, sideRect);
|
|
|
|
|
|
|
|
sideRect.left = maxX;
|
|
|
|
sideRect.right = view->Bounds().right;
|
2022-06-12 12:49:11 -05:00
|
|
|
if (right != NULL && sideRect.Intersects(updateRect))
|
2022-06-11 21:26:46 -05:00
|
|
|
view->DrawBitmap(right, sideRect);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BBitmap*
|
2022-06-12 12:08:29 -05:00
|
|
|
ImageControlLook::_Image(const char* type, uint32 state, uint32 side)
|
2022-06-11 21:26:46 -05:00
|
|
|
{
|
2022-06-12 12:08:29 -05:00
|
|
|
SidedImages* sideList = NULL;
|
|
|
|
UnsidedImages* nosideList = NULL;
|
|
|
|
BBitmap* image = NULL;
|
|
|
|
|
|
|
|
if (strcmp(type, "Button") == 0)
|
|
|
|
sideList = &fButton;
|
|
|
|
else if (strcmp(type, "CheckBox-Unchecked") == 0)
|
|
|
|
nosideList = &fCheckBox_Unchecked;
|
|
|
|
else if (strcmp(type, "CheckBox-Checked") == 0)
|
|
|
|
nosideList = &fCheckBox_Checked;
|
2022-06-12 12:49:11 -05:00
|
|
|
else if (strcmp(type, "SliderThumb") == 0)
|
|
|
|
nosideList = &fSliderThumb;
|
|
|
|
else if (strcmp(type, "SliderTriangle") == 0)
|
|
|
|
nosideList = &fSliderTriangle;
|
2022-06-12 12:08:29 -05:00
|
|
|
|
|
|
|
if (sideList != NULL && (*sideList)[side][state] == NULL)
|
|
|
|
(*sideList)[side][state] = BTranslationUtils::GetBitmapFile(_ImagePath(type, state, side));
|
|
|
|
if (sideList != NULL)
|
|
|
|
image = (*sideList)[side][state];
|
|
|
|
|
|
|
|
if (nosideList != NULL && (*nosideList)[state] == NULL)
|
|
|
|
(*nosideList)[state] = BTranslationUtils::GetBitmapFile(_ImagePath(type, state));
|
|
|
|
if (nosideList != NULL)
|
|
|
|
image = (*nosideList)[state];
|
|
|
|
|
|
|
|
return image;
|
2022-06-11 21:26:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char*
|
2022-06-12 12:08:29 -05:00
|
|
|
ImageControlLook::_ImagePath(const char* type, uint32 state, uint32 side)
|
2022-06-11 21:26:46 -05:00
|
|
|
{
|
|
|
|
BString leaf = kStates[state];
|
|
|
|
leaf << kSides[side];
|
|
|
|
|
|
|
|
BPath imgPath(fImageRoot.Path());
|
|
|
|
imgPath.Append(type);
|
|
|
|
imgPath.Append(leaf);
|
2022-06-12 12:08:29 -05:00
|
|
|
printf("[ImageControlLook] Searching for %s…\n", imgPath.Path());
|
2022-06-11 21:26:46 -05:00
|
|
|
return imgPath.Path();
|
2022-06-11 13:00:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-06-12 12:49:11 -05:00
|
|
|
uint32
|
|
|
|
ImageControlLook::_FlagsToState(uint32 flags)
|
|
|
|
{
|
|
|
|
uint32 state = ICL_NORMAL;
|
|
|
|
if (flags & B_DISABLED)
|
|
|
|
state = ICL_DISABLED;
|
|
|
|
else if (flags & (B_ACTIVATED | B_PARTIALLY_ACTIVATED | B_CLICKED))
|
|
|
|
state = ICL_ACTIVATED;
|
|
|
|
else if (flags & (B_HOVER | B_FOCUSED))
|
|
|
|
state = ICL_HOVER;
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-06-11 13:00:24 -05:00
|
|
|
extern "C" BControlLook* (instantiate_control_look)(image_id id)
|
|
|
|
{
|
|
|
|
return new (std::nothrow)ImageControlLook(id);
|
|
|
|
}
|