#include "prefs.h" #include #include #include #include #include #include #include #include "main_window.h" using namespace Looper::Options; #define CMD_UPDATE_LABEL_SETTING 0x1000 #define CMD_FRONTEND 0x1001 #define CMD_SET_SETTING 0x1002 #define CMD_REVERT 0x1003 #define CMD_APPLY 0x1004 #define CMD_SET_SETTING_CHECKBOX = 0x1005 bool show_icons, show_labels; HaikuPrefsWindow::HaikuPrefsWindow(BLooper *next_handler) : BWindow(BRect(100, 100, 0, 0), "Preferences", B_TITLED_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS) { this->next_handler = next_handler; for (auto &cat : get_cat_data()) { switch (cat.get_type()) { case CatDataType::Memory: { MemoryCat mem_cat = cat.get_memory_cat(); AddCat(cat.get_name(), LoadCat(mem_cat.get_ptr(), mem_cat.get_len(), cat.get_path().c_str())); } break; case CatDataType::File: { fs::path cat_path = cat.get_path(); AddCat(cat.get_name(), LoadCat(cat_path.c_str())); } break; } } auto *root_layout = new BGroupLayout(B_VERTICAL); SetLayout(root_layout); root_layout->SetSpacing(0.0); restart_warning = new BStringView("prefs:restart_needed", "A restart is needed to apply some changes."); root_layout->AddView(restart_warning); restart_warning->Hide(); frontend_popup = new BOptionPopUp("prefs:frontend", "Frontend", new BMessage(CMD_FRONTEND)); auto frontend = get_option("ui.frontend", "haiku"); for (auto &kv : UIBackend::backends) { UIBackend *backend = kv.second; const char *name = backend->get_name().c_str(); frontend_popup->AddOption(name, (int32)backend_ids.size()); std::string id = backend->get_id(); if (id == frontend) cur_option = (int32)backend_ids.size(); backend_ids.push_back(id); } BLayoutItem *frontend_item = root_layout->AddView(frontend_popup); BAlignment align; align.SetVertical(B_ALIGN_TOP); frontend_item->SetExplicitAlignment(align); BBox *box = new BBox("prefs:label_settings_box"); box->SetLabel("Labels and Icons"); auto *label_settings_group = new BGroupView(B_VERTICAL); BGroupLayout *label_settings_layout = label_settings_group->GroupLayout(); BMessage *labels_only_msg = new BMessage(CMD_SET_SETTING); labels_only_msg->AddString("pref_path", "ui.haiku.label_setting"); labels_only_msg->AddString("pref_value", "labels"); labels_only = new BRadioButton("prefs:labels_only", "Labels Only", labels_only_msg); BMessage *icons_only_msg = new BMessage(CMD_SET_SETTING); icons_only_msg->AddString("pref_path", "ui.haiku.label_setting"); icons_only_msg->AddString("pref_value", "icons"); icons_only = new BRadioButton("prefs:icons_only", "Icons Only", icons_only_msg); BMessage *both_labels_icons_msg = new BMessage(CMD_SET_SETTING); both_labels_icons_msg->AddString("pref_path", "ui.haiku.label_setting"); both_labels_icons_msg->AddString("pref_value", "both"); both_labels_icons = new BRadioButton("prefs:both_labels_and_icons", "Both", both_labels_icons_msg); label_settings_layout->AddView(labels_only); label_settings_layout->AddView(icons_only); label_settings_layout->AddView(both_labels_icons); BMessage *cat_enable_msg = new BMessage(CMD_SET_SETTING_CHECKBOX); cat_enable_msg->AddString("pref_path", "ui.cat_enable"); cat_enable = new BCheckBox("Enable Cat", cat_enable_msg); BGroupView *cat_group = new BGroupView(B_VERTICAL); BGroupLayout *cat_layout = cat_group->GroupLayout(); for (auto &kv : cats) { 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); cat_btns[kv.first] = cat_radio; BBitmap *cat_bmp = kv.second; BRect src = cat_bmp->bounds(); float w = src.Width(), h = src.Height(); float rw = cat_radio->Bounds().Width(), rh = cat_radio->Bounds().Height(); if (w > rw || h > rh) { float aspect = w / h; if (h > rh) { h = rh; w = h * aspect; } if (w > rw) { w = rw; h = h / aspect; } } BRect dst(rw - w, (rh - h) / 2, rw, rh); cat_radio->SetOverlayBitmap(cat_bmp, src, dst, B_FOLLOW_RIGHT|B_FOLLOW_TOP_BOTTOM); } root_layout->AddView(box, 3.0); BGroupView *btn_view = new BGroupView(B_HORIZONTAL); BGroupLayout *btn_box = btn_view->GroupLayout(); revert_btn = new BButton("prefs:revert", "Revert", new BMessage(CMD_REVERT)); apply_btn = new BButton("prefs:apply", "Apply", new BMessage(CMD_APPLY)); root_layout->AddView(btn_view); btn_box->AddView(revert_btn); btn_box->AddView(apply_btn); { auto *msg = new BMessage(CMD_REVERT); MessageReceived(msg); delete msg; } } bool HaikuPrefsWindow::QuitRequested() { Hide(); return quitting; } void HaikuPrefsWindow::set_options_changed(bool changed) { revert_btn->SetEnabled(changed); apply_btn->SetEnabled(changed); } void HaikuPrefsWindow::update_label_setting() { std::map label_settings_map({{"labels", labels_only}, {"icons", icons_only}, {"both", both_labels_icons}}); auto cur_radio_btn = labels_only; if (!label_settings_map.contains(new_label_setting)) { new_label_setting = "icons"; } cur_radio_btn = label_settings_map[new_label_setting]; show_icons = new_label_setting != "labels"; show_labels = new_label_setting != "icons"; cur_radio_btn->SetValue(B_CONTROL_ON); } void HaikuPrefsWindow::MessageReceived(BMessage *msg) { if (msg->IsSystem()) return; switch (msg->what) { case CMD_APPLY: { set_options_changed(false); set_option("ui.frontend", new_frontend); if (new_frontend != "haiku") restart_warning->Show(); else restart_warning->Hide(); set_option("ui.haiku.label_setting", new_label_setting); update_label_setting(); set_option("ui.cat", cat_id); set_option("ui.enable_cat", enable_cat); next_handler->PostMessage(CMD_UPDATE_LABEL_SETTING); BMessage *cat_msg = new BMessage(CMD_SET_CAT); if (enable_cat) cat_msg->AddBitmap("cat", cats[cat_id]) next_handler->PostMessage(cat_msg); } break; case CMD_REVERT: { set_options_changed(false); new_label_setting = get_option("ui.haiku.label_setting", "icons"); new_frontend = get_option("ui.frontend", "haiku"); if (new_frontend != "haiku") restart_warning->Show(); else restart_warning->Hide(); for (size_t i = 0; i < backend_ids.size(); i++) { int32 backend_id = (int32)i; if (backend_ids[i] == new_frontend) { frontend_popup->SetValue(backend_id); break; } } cat_btns[cat_id].SetValue(B_CONTROL_OFF); cat_id = get_option("ui.cat", cats.empty() ? "" : cats.begin()->first); if (cat_btns.contains(cat_id)) cat_btns[cat_id].SetValue(B_CONTROL_ON); enable_cat = get_option("ui.enable_cat", false); cat_enable->SetValue(enable_cat ? B_CONTROL_ON : B_CONTROL_OFF); update_label_setting(); next_handler->PostMessage(CMD_UPDATE_LABEL_SETTING); BMessage *cat_msg = new BMessage(CMD_SET_CAT); if (enable_cat) cat_msg->AddBitmap("cat", cats[cat_id]) next_handler->PostMessage(cat_msg); } break; case CMD_FRONTEND: { auto option = msg->GetInt32("be:value", cur_option); if (backend_ids.size() < option && option >= 0) { new_frontend = backend_ids[option]; } set_options_changed(true); } break; case CMD_SET_SETTING: { const char *setting; if (msg->FindString("pref_path", &setting) == B_OK) { const char *setting_value; int32 setting_value_int32; if (msg->FindString("pref_value", &setting_value) == B_OK) { if (std::string(setting) == "ui.haiku.label_setting") { new_label_setting = setting_value; set_options_changed(true); } else if (std::string(setting) == "ui.cat") { cat_id = setting_value; set_options_changed(true); } } } } break; case CMD_SET_SETTING_CHECKBOX: { const char *setting; if (msg->FindString("pref_path", &setting) == B_OK) { int32 setting_value_int32; if (msg->FindInt32("be:value", &setting_value_int32) == B_OK) { if (std::string(setting) == "ui.enable_cat") { enable_cat = setting_value_int32 == B_CONTROL_ON; set_options_changed(true); } } } } break; } }