diff --git a/backends/ui/haiku/CMakeLists.txt b/backends/ui/haiku/CMakeLists.txt index 40002c6..2dd9409 100644 --- a/backends/ui/haiku/CMakeLists.txt +++ b/backends/ui/haiku/CMakeLists.txt @@ -1,4 +1,4 @@ -set(BACKEND_HAIKU_SRC_BASE main.cpp main_window.cpp prefs.cpp slider.cpp slider.h main.h main_window.h aboutwindow.h aboutwindow.cpp prefs.h) +set(BACKEND_HAIKU_SRC_BASE main.cpp main_window.cpp prefs.cpp slider.cpp slider.h main.h main_window.h aboutwindow.h aboutwindow.cpp prefs.h image_view.cpp image_view.h) set(BACKEND_HAIKU_SRC ) foreach(SRC IN ITEMS ${BACKEND_HAIKU_SRC_BASE}) set(BACKEND_HAIKU_SRC ${BACKEND_HAIKU_SRC} ${CMAKE_CURRENT_SOURCE_DIR}/${SRC}) diff --git a/backends/ui/haiku/image_view.cpp b/backends/ui/haiku/image_view.cpp new file mode 100644 index 0000000..0d44d54 --- /dev/null +++ b/backends/ui/haiku/image_view.cpp @@ -0,0 +1,95 @@ +#include "image_view.h" +#include + + +LImageView::LImageView(const char *name, BBitmap *bitmap, BAlignment align) : BView(name, B_SUPPORTS_LAYOUT|B_FRAME_EVENTS|B_WILL_DRAW) +{ + SetBitmap(bitmap); + SetAlignment(align); +} +void LImageView::SetBitmap(BBitmap *bitmap) { + this->bitmap = bitmap; + Invalidate(); +} +void LImageView::SetAlignment(BAlignment align) { + this->align = align; + Invalidate(); +} +BBitmap *LImageView::Bitmap() { + return bitmap; +} +BAlignment LImageView::Alignment() { + return align; +} + +void LImageView::FrameResized(float newW, float newH) { + Invalidate(); +} +void LImageView::Draw(BRect updateRect) { + AdoptSystemColors(); + SetDrawingMode(B_OP_BLEND); + FillRect(img_bounds); + if (bitmap == NULL) return; // Handle null image. + int x = 0, y = 0; + int mw, mh; + int bw, bh; + bw = bitmap->Bounds().Width(); + bh = bitmap->Bounds().Height(); + int iw = bw, ih = bh; + mw = Bounds().Width(); + mh = Bounds().Height(); + float wr = ((float)mw) / ((float)bw); + float hr = ((float)mh) / ((float)bh); + if (wr < hr) { + iw *= wr; + ih *= wr; + } else { + iw *= hr; + ih *= hr; + } + + + switch (align.Horizontal()) { + case B_ALIGN_LEFT: { + x = 0; + } break; + case B_ALIGN_HORIZONTAL_CENTER: { + x = (mw - iw) / 2; + } break; + case B_ALIGN_RIGHT: { + x = mw - iw; + } break; + } + switch (align.Vertical()) { + case B_ALIGN_TOP: { + y = 0; + } break; + case B_ALIGN_VERTICAL_CENTER: { + y = (mh - ih) / 2; + } break; + case B_ALIGN_BOTTOM: { + y = mh - ih; + } break; + } + BRect bitmap_rect(0, 0, bw, bh); + BRect draw_rect(x, y, iw + x, ih + y); + int left = updateRect.left; + int right = updateRect.right; + int top = updateRect.top; + int bottom = updateRect.bottom; + int x2 = x + bw; + int y2 = y + bh; + FillRect(draw_rect); + DrawBitmap(bitmap, bitmap_rect, draw_rect); + img_bounds = draw_rect; +} + +void LImageView::GetPreferredSize(float *w, float *h) { + if (!bitmap) { + *w = 0; + *h = 0; + return; + } + *w = bitmap->Bounds().Width(); + *h = bitmap->Bounds().Height(); +} diff --git a/backends/ui/haiku/image_view.h b/backends/ui/haiku/image_view.h new file mode 100644 index 0000000..2746a91 --- /dev/null +++ b/backends/ui/haiku/image_view.h @@ -0,0 +1,21 @@ +#pragma once +#include +#include +#include +#include + +class LImageView : public BView { + BBitmap *bitmap; + BAlignment align; + BRect img_bounds; +public: + void GetPreferredSize(float *w, float *h) override; + void SetBitmap(BBitmap *bitmap); + BBitmap *Bitmap(); + void SetAlignment(BAlignment align); + BAlignment Alignment(); + void Draw(BRect updateRect) override; + void FrameResized(float newW, float newH) override; + + LImageView(const char *name, BBitmap *bitmap, BAlignment align); +}; diff --git a/backends/ui/haiku/main_window.cpp b/backends/ui/haiku/main_window.cpp index b3412bc..5e85b16 100644 --- a/backends/ui/haiku/main_window.cpp +++ b/backends/ui/haiku/main_window.cpp @@ -97,7 +97,7 @@ HaikuLooperWindow::HaikuLooperWindow(Playback *playback) : BWindow(BRect(100, 10 menu_bar->AddItem(file_menu); menu_bar->AddItem(help_menu); layout->AddView(menu_bar); - spacer = new BView("spacer", B_SUPPORTS_LAYOUT|B_FRAME_EVENTS); + spacer = new LImageView("spacer", NULL, BAlignment(B_ALIGN_RIGHT, B_ALIGN_BOTTOM)); spacer->SetExplicitPreferredSize(BSize(0, 0)); spacer->SetExplicitMinSize(BSize(0, 0)); layout->AddView(spacer); @@ -184,9 +184,9 @@ void HaikuLooperWindow::UpdateCat(BBitmap *cat) { } } BRect dst(sw - w, sh - h, w, h); - spacer->SetViewOverlay(cat, src, dst, NULL, B_FOLLOW_RIGHT|B_FOLLOW_BOTTOM); + spacer->SetBitmap(cat); } else { - spacer->ClearViewOverlay(); + spacer->SetBitmap(NULL); } UnlockLooper(); } diff --git a/backends/ui/haiku/main_window.h b/backends/ui/haiku/main_window.h index 014fe34..51d5cbc 100644 --- a/backends/ui/haiku/main_window.h +++ b/backends/ui/haiku/main_window.h @@ -14,6 +14,7 @@ #include "aboutwindow.h" #include "slider.h" #include "prefs.h" +#include "image_view.h" #include #include #define CMD_UPDATE_LABEL_SETTING 0x1000 @@ -59,7 +60,7 @@ class HaikuLooperWindow : public BWindow { BButton *restart_btn; BButton *stop_btn; BButton *pause_resume_btn; - BView *spacer; + LImageView *spacer; void UpdateCat(BBitmap *cat); bool volume_clicked = false; bool speed_clicked = false; diff --git a/backends/ui/haiku/prefs.cpp b/backends/ui/haiku/prefs.cpp index f307838..b099329 100644 --- a/backends/ui/haiku/prefs.cpp +++ b/backends/ui/haiku/prefs.cpp @@ -9,6 +9,7 @@ #include "main_window.h" #include #include +#include "image_view.h" using namespace Looper::Options; #define CMD_UPDATE_LABEL_SETTING 0x1000 #define CMD_FRONTEND 0x1001 @@ -101,7 +102,8 @@ HaikuPrefsWindow::HaikuPrefsWindow(BLooper *next_handler) : BWindow(BRect(100, 1 BMessage *msg = new BMessage(CMD_SET_SETTING); msg->AddString("pref_path", "ui.cat"); msg->AddString("pref_value", kv.first.c_str()); - BRadioButton *cat_radio = new BRadioButton(fmt::format("prefs:cat:{}", kv.first).c_str(), msg); + BGroupView *cat_row = new BGroupView(B_HORIZONTAL); + BRadioButton *cat_radio = new BRadioButton(kv.first.c_str(), msg); cat_btns[kv.first] = cat_radio; BBitmap *cat_bmp = kv.second; BRect src = cat_bmp->Bounds(); @@ -119,14 +121,16 @@ HaikuPrefsWindow::HaikuPrefsWindow(BLooper *next_handler) : BWindow(BRect(100, 1 } } BRect dst(rw - w, (rh - h) / 2, rw, rh); - LockLooper(); - cat_radio->SetViewOverlay(cat_bmp, src, dst, NULL, B_FOLLOW_RIGHT|B_FOLLOW_TOP_BOTTOM); - UnlockLooper(); - cat_layout->AddView(cat_radio); + LImageView *img_view = new LImageView("prefs:cat:preview", cat_bmp, BAlignment(B_ALIGN_RIGHT, B_ALIGN_BOTTOM)); + img_view->SetExplicitMinSize(BSize(16, 16)); + img_view->SetExplicitPreferredSize(BSize(16, 16)); + cat_row->AddChild(cat_radio); + cat_row->AddChild(img_view); + cat_layout->AddView(cat_row); } root_layout->AddView(box, 3.0); cat_box->AddChild(cat_group); - root_layout->AddView(cat_enable); + root_layout->AddView(cat_enable, 1.0); root_layout->AddView(cat_box, 3.0); BGroupView *btn_view = new BGroupView(B_HORIZONTAL); BGroupLayout *btn_box = btn_view->GroupLayout();