/* * Copyright 2023 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * John Scipione, jscipione@gmail.com */ #include "StatusMenuField.h" #include #include #include #include #include #include #include #include #include #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "Modifier keys window" #ifdef DEBUG_ALERT # define FTRACE(x) fprintf(x) #else # define FTRACE(x) /* nothing */ #endif static const char* kDuplicate = "duplicate"; static const char* kUnmatched = "unmatched"; // #pragma mark - StatusMenuItem StatusMenuItem::StatusMenuItem(const char* name, BMessage* message) : BMenuItem(name, message), fIcon(NULL) { } StatusMenuItem::StatusMenuItem(BMessage* archive) : BMenuItem(archive), fIcon(NULL) { } BArchivable* StatusMenuItem::Instantiate(BMessage* data) { if (validate_instantiation(data, "StatusMenuItem")) return new StatusMenuItem(data); return NULL; } status_t StatusMenuItem::Archive(BMessage* data, bool deep) const { status_t result = BMenuItem::Archive(data, deep); return result; } void StatusMenuItem::DrawContent() { if (fIcon == NULL) return BMenuItem::DrawContent(); // blend transparency Menu()->SetDrawingMode(B_OP_ALPHA); Menu()->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); // draw bitmap Menu()->DrawBitmapAsync(fIcon, IconRect().LeftTop()); BMenuItem::DrawContent(); } void StatusMenuItem::GetContentSize(float* _width, float* _height) { float width; float height; BMenuItem::GetContentSize(&width, &height); // prevent label from drawing over icon if (_width != NULL) *_width = Menu()->Bounds().Width() - IconRect().Width() - Spacing() * 4; if (_height != NULL) *_height = height; } BBitmap* StatusMenuItem::Icon() { return fIcon; } void StatusMenuItem::SetIcon(BBitmap* icon) { fIcon = icon; } BRect StatusMenuItem::IconRect() { BRect bounds(Menu()->Bounds()); bounds.top += roundf(Spacing() / 2); // center inside menu field vertically bounds.right -= Spacing() * 3; // move inside menu field horizontally return BLayoutUtils::AlignInFrame(bounds, IconSize(), BAlignment(B_ALIGN_RIGHT, B_ALIGN_TOP)); } BSize StatusMenuItem::IconSize() { return be_control_look->ComposeIconSize(B_MINI_ICON); } float StatusMenuItem::Spacing() { return be_control_look->DefaultLabelSpacing(); } // #pragma mark - StatusMenuField StatusMenuField::StatusMenuField(const char* label, BMenu* menu) : BMenuField(label, menu), fStatus(B_EMPTY_STRING), fStopIcon(NULL), fWarnIcon(NULL) { _FillIcons(); } StatusMenuField::~StatusMenuField() { delete fStopIcon; delete fWarnIcon; } void StatusMenuField::SetDuplicate(bool on) { ShowStopIcon(on); on ? SetStatus(kDuplicate) : ClearStatus(); Invalidate(); } void StatusMenuField::SetUnmatched(bool on) { ShowWarnIcon(on); on ? SetStatus(kUnmatched) : ClearStatus(); Invalidate(); } void StatusMenuField::ShowStopIcon(bool show) { // show or hide the stop icon StatusMenuItem* item = dynamic_cast(MenuItem()); if (item != NULL) item->SetIcon(show ? fStopIcon : NULL); } void StatusMenuField::ShowWarnIcon(bool show) { // show or hide the warn icon StatusMenuItem* item = dynamic_cast(MenuItem()); if (item != NULL) item->SetIcon(show ? fWarnIcon : NULL); } void StatusMenuField::ClearStatus() { fStatus = B_EMPTY_STRING; SetToolTip((const char*)NULL); } void StatusMenuField::SetStatus(BString status) { fStatus = status; const char* tooltip = B_EMPTY_STRING; if (fStatus == kDuplicate) tooltip = B_TRANSLATE("Error: duplicate keys"); else if (fStatus == kUnmatched) tooltip = B_TRANSLATE("Warning: left and right key roles do not match"); SetToolTip(tooltip); } // #pragma mark - StatusMenuField private methods void StatusMenuField::_FillIcons() { // fill out the icons with the stop and warn icons from app_server // TODO find better icons if (fStopIcon == NULL) { // allocate the fStopIcon bitmap fStopIcon = new (std::nothrow) BBitmap(_IconRect(), 0, B_RGBA32); if (fStopIcon == NULL || fStopIcon->InitCheck() != B_OK) { FTRACE((stderr, "MKW::_FillIcons() - No memory for stop bitmap\n")); delete fStopIcon; fStopIcon = NULL; return; } // load dialog-error icon bitmap if (BIconUtils::GetSystemIcon("dialog-error", fStopIcon) != B_OK) { delete fStopIcon; fStopIcon = NULL; return; } } if (fWarnIcon == NULL) { // allocate the fWarnIcon bitmap fWarnIcon = new (std::nothrow) BBitmap(_IconRect(), 0, B_RGBA32); if (fWarnIcon == NULL || fWarnIcon->InitCheck() != B_OK) { FTRACE((stderr, "MKW::_FillIcons() - No memory for warn bitmap\n")); delete fWarnIcon; fWarnIcon = NULL; return; } // load dialog-warning icon bitmap if (BIconUtils::GetSystemIcon("dialog-warning", fWarnIcon) != B_OK) { delete fWarnIcon; fWarnIcon = NULL; return; } } } BRect StatusMenuField::_IconRect() { BSize iconSize = be_control_look->ComposeIconSize(B_MINI_ICON); return BRect(0, 0, iconSize.Width() - 1, iconSize.Height() - 1); }