1 /* 2 * Copyright 2021, Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Emmanuel Gil Peyrot 7 */ 8 9 10 #include "ConfigView.h" 11 12 #include <stdio.h> 13 #include <string.h> 14 15 #include <Catalog.h> 16 #include <CheckBox.h> 17 #include <LayoutBuilder.h> 18 #include <MenuField.h> 19 #include <MenuItem.h> 20 #include <Message.h> 21 #include <PopUpMenu.h> 22 #include <Slider.h> 23 #include <StringView.h> 24 25 #include "avif/avif.h" 26 27 #include "TranslatorSettings.h" 28 #include "AVIFTranslator.h" 29 30 31 #undef B_TRANSLATION_CONTEXT 32 #define B_TRANSLATION_CONTEXT "ConfigView" 33 34 35 static const uint32 kMsgLossless = 'losl'; 36 static const uint32 kMsgPixelFormat = 'pfmt'; 37 static const uint32 kMsgQuality = 'qlty'; 38 static const uint32 kMsgSpeed = 'sped'; 39 static const uint32 kMsgTilesHorizontal = 'tilh'; 40 static const uint32 kMsgTilesVertical = 'tilv'; 41 42 43 ConfigView::ConfigView(TranslatorSettings* settings) 44 : 45 BGroupView(B_TRANSLATE("AVIFTranslator Settings"), B_VERTICAL), 46 fSettings(settings) 47 { 48 SetViewUIColor(B_PANEL_BACKGROUND_COLOR); 49 50 BStringView* title = new BStringView("title", 51 B_TRANSLATE("AVIF image translator")); 52 title->SetFont(be_bold_font); 53 54 char versionString[256]; 55 sprintf(versionString, "v%d.%d.%d, %s", 56 static_cast<int>(B_TRANSLATION_MAJOR_VERSION(AVIF_TRANSLATOR_VERSION)), 57 static_cast<int>(B_TRANSLATION_MINOR_VERSION(AVIF_TRANSLATOR_VERSION)), 58 static_cast<int>(B_TRANSLATION_REVISION_VERSION( 59 AVIF_TRANSLATOR_VERSION)), 60 __DATE__); 61 62 BStringView* version = new BStringView("version", versionString); 63 64 BString copyrightsText; 65 BStringView *copyrightView = new BStringView("Copyright", 66 B_TRANSLATE(B_UTF8_COPYRIGHT "2021 Emmanuel Gil Peyrot")); 67 68 BString libavifInfo = B_TRANSLATE( 69 "Based on libavif %version%"); 70 libavifInfo.ReplaceAll("%version%", avifVersion()); 71 72 BStringView *copyright2View = new BStringView("Copyright2", 73 libavifInfo.String()); 74 BStringView *copyright3View = new BStringView("Copyright3", 75 B_TRANSLATE(B_UTF8_COPYRIGHT "2019 Joe Drago. All rights reserved.")); 76 77 // output parameters 78 79 fLosslessCheckBox = new BCheckBox("lossless", 80 B_TRANSLATE("Lossless"), new BMessage(kMsgLossless)); 81 bool lossless; 82 fSettings->SetGetBool(AVIF_SETTING_LOSSLESS, &lossless); 83 if (lossless) 84 fLosslessCheckBox->SetValue(B_CONTROL_ON); 85 86 fPixelFormatMenu = new BPopUpMenu(B_TRANSLATE("Pixel format")); 87 88 static const avifPixelFormat pixelFormats[4] = { 89 AVIF_PIXEL_FORMAT_YUV444, 90 AVIF_PIXEL_FORMAT_YUV420, 91 AVIF_PIXEL_FORMAT_YUV400, 92 AVIF_PIXEL_FORMAT_YUV422, 93 }; 94 for (size_t i = 0; i < 4; ++i) { 95 BMessage* msg = new BMessage(kMsgPixelFormat); 96 msg->AddInt32("value", pixelFormats[i]); 97 98 BMenuItem* item = new BMenuItem( 99 avifPixelFormatToString(pixelFormats[i]), msg); 100 if (fSettings->SetGetInt32(AVIF_SETTING_PIXEL_FORMAT) == pixelFormats[i]) 101 item->SetMarked(true); 102 fPixelFormatMenu->AddItem(item); 103 } 104 105 BMenuField* pixelFormatField = new BMenuField(B_TRANSLATE("Pixel format:"), 106 fPixelFormatMenu); 107 108 rgb_color barColor = { 0, 0, 229, 255 }; 109 110 fQualitySlider = new BSlider("quality", B_TRANSLATE("Output quality:"), 111 new BMessage(kMsgQuality), AVIF_QUANTIZER_BEST_QUALITY, 112 AVIF_QUANTIZER_WORST_QUALITY, B_HORIZONTAL, B_BLOCK_THUMB); 113 fQualitySlider->SetHashMarks(B_HASH_MARKS_BOTTOM); 114 fQualitySlider->SetHashMarkCount(8); 115 fQualitySlider->SetLimitLabels(B_TRANSLATE("Best"), B_TRANSLATE("Worst")); 116 fQualitySlider->UseFillColor(true, &barColor); 117 fQualitySlider->SetValue(fSettings->SetGetInt32(AVIF_SETTING_QUALITY)); 118 fQualitySlider->SetEnabled(!lossless); 119 120 fSpeedSlider = new BSlider("speed", B_TRANSLATE("Compression speed:"), 121 new BMessage(kMsgSpeed), AVIF_SPEED_SLOWEST, 122 AVIF_SPEED_FASTEST, B_HORIZONTAL, B_BLOCK_THUMB); 123 fSpeedSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); 124 fSpeedSlider->SetHashMarkCount(11); 125 fSpeedSlider->SetLimitLabels(B_TRANSLATE("Slow"), 126 B_TRANSLATE("Faster but worse quality")); 127 fSpeedSlider->UseFillColor(true, &barColor); 128 fSpeedSlider->SetValue(fSettings->SetGetInt32(AVIF_SETTING_SPEED)); 129 130 fHTilesSlider = new BSlider("htiles", B_TRANSLATE("Horizontal tiles:"), 131 new BMessage(kMsgTilesHorizontal), 1, 6, B_HORIZONTAL, 132 B_BLOCK_THUMB); 133 fHTilesSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); 134 fHTilesSlider->SetHashMarkCount(6); 135 fHTilesSlider->SetLimitLabels(B_TRANSLATE("1"), 136 B_TRANSLATE("2⁶")); 137 fHTilesSlider->UseFillColor(true, &barColor); 138 fHTilesSlider->SetValue( 139 fSettings->SetGetInt32(AVIF_SETTING_TILES_HORIZONTAL)); 140 141 fVTilesSlider = new BSlider("vtiles", B_TRANSLATE("Vertical tiles:"), 142 new BMessage(kMsgTilesVertical), 1, 6, B_HORIZONTAL, 143 B_BLOCK_THUMB); 144 fVTilesSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); 145 fVTilesSlider->SetHashMarkCount(6); 146 fVTilesSlider->SetLimitLabels(B_TRANSLATE("1"), 147 B_TRANSLATE("2⁶")); 148 fVTilesSlider->UseFillColor(true, &barColor); 149 fVTilesSlider->SetValue( 150 fSettings->SetGetInt32(AVIF_SETTING_TILES_VERTICAL)); 151 152 // Build the layout 153 BLayoutBuilder::Group<>(this, B_VERTICAL, 0) 154 .SetInsets(B_USE_DEFAULT_SPACING) 155 .Add(title) 156 .Add(version) 157 .Add(copyrightView) 158 .AddGlue() 159 .Add(fLosslessCheckBox) 160 .AddGrid(B_USE_DEFAULT_SPACING, B_USE_SMALL_SPACING) 161 .Add(pixelFormatField->CreateLabelLayoutItem(), 0, 0) 162 .AddGroup(B_HORIZONTAL, 0.0f, 1, 0) 163 .Add(pixelFormatField->CreateMenuBarLayoutItem(), 0.0f) 164 .AddGlue() 165 .End() 166 .End() 167 .Add(fQualitySlider) 168 .Add(fSpeedSlider) 169 .Add(fHTilesSlider) 170 .Add(fVTilesSlider) 171 .AddGlue() 172 .Add(copyright2View) 173 .Add(copyright3View); 174 } 175 176 177 ConfigView::~ConfigView() 178 { 179 fSettings->Release(); 180 } 181 182 183 void 184 ConfigView::AttachedToWindow() 185 { 186 BGroupView::AttachedToWindow(); 187 188 fQualitySlider->SetTarget(this); 189 fSpeedSlider->SetTarget(this); 190 fHTilesSlider->SetTarget(this); 191 fVTilesSlider->SetTarget(this); 192 193 if (Parent() == NULL && Window()->GetLayout() == NULL) { 194 Window()->SetLayout(new BGroupLayout(B_VERTICAL)); 195 Window()->ResizeTo(PreferredSize().Width(), 196 PreferredSize().Height()); 197 } 198 } 199 200 201 void 202 ConfigView::MessageReceived(BMessage* message) 203 { 204 struct { 205 const char* name; 206 uint32 what; 207 TranSettingType type; 208 } maps[] = { 209 { AVIF_SETTING_LOSSLESS, kMsgLossless, TRAN_SETTING_BOOL }, 210 { AVIF_SETTING_PIXEL_FORMAT, kMsgPixelFormat, 211 TRAN_SETTING_INT32 }, 212 { AVIF_SETTING_QUALITY, kMsgQuality, TRAN_SETTING_INT32 }, 213 { AVIF_SETTING_SPEED, kMsgSpeed, TRAN_SETTING_INT32 }, 214 { AVIF_SETTING_TILES_HORIZONTAL, kMsgTilesHorizontal, 215 TRAN_SETTING_INT32 }, 216 { AVIF_SETTING_TILES_VERTICAL, kMsgTilesVertical, 217 TRAN_SETTING_INT32 }, 218 { NULL } 219 }; 220 221 int i; 222 for (i = 0; maps[i].name != NULL; i++) { 223 if (maps[i].what == message->what) 224 break; 225 } 226 227 if (maps[i].name == NULL) { 228 BGroupView::MessageReceived(message); 229 return; 230 } 231 232 int32 value; 233 if (message->FindInt32("value", &value) == B_OK 234 || message->FindInt32("be:value", &value) == B_OK) { 235 switch(maps[i].type) { 236 case TRAN_SETTING_BOOL: 237 { 238 bool boolValue = value; 239 fSettings->SetGetBool(maps[i].name, &boolValue); 240 if (maps[i].what == kMsgLossless) 241 fSpeedSlider->SetEnabled(!boolValue); 242 break; 243 } 244 case TRAN_SETTING_INT32: 245 fSettings->SetGetInt32(maps[i].name, &value); 246 break; 247 } 248 fSettings->SaveSettings(); 249 } 250 } 251