1 /* 2 * Copyright 2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9 #include "SavePanel.h" 10 11 #include <stdio.h> 12 #include <string.h> 13 14 #include <Alert.h> 15 #include <Button.h> 16 #include <MenuBar.h> 17 #include <MenuField.h> 18 #include <PopUpMenu.h> 19 #include <ScrollBar.h> 20 #include <TextControl.h> 21 #include <TranslationKit.h> 22 #include <View.h> 23 #include <Window.h> 24 25 #include "Exporter.h" 26 #include "IconEditorApp.h" 27 #include "Panel.h" 28 29 enum { 30 MSG_FORMAT = 'sfpf', 31 MSG_SETTINGS = 'sfps', 32 }; 33 34 // SaveItem class 35 SaveItem::SaveItem(const char* name, 36 BMessage* message, 37 uint32 exportMode) 38 : BMenuItem(name, message), 39 fExportMode(exportMode) 40 { 41 } 42 43 // #pragma mark - 44 45 // SavePanel class 46 SavePanel::SavePanel(const char* name, 47 BMessenger* target, 48 entry_ref* startDirectory, 49 uint32 nodeFlavors, 50 bool allowMultipleSelection, 51 BMessage* message, 52 BRefFilter* filter, 53 bool modal, 54 bool hideWhenDone) 55 : BFilePanel(B_SAVE_PANEL, target, startDirectory, 56 nodeFlavors, allowMultipleSelection, 57 message, filter, modal, hideWhenDone), 58 BHandler(name), 59 fConfigWindow(NULL), 60 fFormatM(NULL), 61 fExportMode(EXPORT_MODE_ICON_RDEF) 62 { 63 BWindow* window = Window(); 64 if (!window || !window->Lock()) 65 return; 66 67 window->SetTitle("Save Image"); 68 69 // add this instance as BHandler to the window's looper 70 window->AddHandler(this); 71 72 // find a couple of important views and mess with their layout 73 BView* background = Window()->ChildAt(0); 74 BButton* cancel = dynamic_cast<BButton*>(background->FindView("cancel button")); 75 BView* textview = background->FindView("text view"); 76 BScrollBar* hscrollbar = dynamic_cast<BScrollBar*>(background->FindView("HScrollBar")); 77 78 if (!background || !cancel || !textview || !hscrollbar) { 79 printf("SavePanel::SavePanel() - couldn't find necessary controls.\n"); 80 return; 81 } 82 83 _BuildMenu(); 84 85 BRect rect = textview->Frame(); 86 rect.top = cancel->Frame().top; 87 font_height fh; 88 be_plain_font->GetHeight(&fh); 89 rect.bottom = rect.top + fh.ascent + fh.descent + 5.0; 90 91 fFormatMF = new BMenuField(rect, "format popup", "Format", fFormatM, true, 92 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM, 93 B_WILL_DRAW | B_NAVIGABLE); 94 fFormatMF->SetDivider(be_plain_font->StringWidth("Format") + 7); 95 fFormatMF->MenuBar()->ResizeToPreferred(); 96 fFormatMF->ResizeToPreferred(); 97 98 float height = fFormatMF->Bounds().Height() + 8.0; 99 100 // find all the views that are in the way and 101 // move up them up the height of the menu field 102 BView *poseview = background->FindView("PoseView"); 103 if (poseview) poseview->ResizeBy(0, -height); 104 BButton *insert = (BButton *)background->FindView("default button"); 105 if (hscrollbar) hscrollbar->MoveBy(0, -height); 106 BScrollBar *vscrollbar = (BScrollBar *)background->FindView("VScrollBar"); 107 if (vscrollbar) vscrollbar->ResizeBy(0, -height); 108 BView *countvw = (BView *)background->FindView("CountVw"); 109 if (countvw) countvw->MoveBy(0, -height); 110 textview->MoveBy(0, -height); 111 112 #if HAIKU_TARGET_PLATFORM_DANO 113 fFormatMF->MoveTo(textview->Frame().left, fFormatMF->Frame().top + 2); 114 #else 115 fFormatMF->MoveTo(textview->Frame().left, fFormatMF->Frame().top); 116 #endif 117 118 background->AddChild(fFormatMF); 119 120 // Build the "Settings" button relative to the format menu 121 rect = cancel->Frame(); 122 rect.OffsetTo(fFormatMF->Frame().right + 5.0, rect.top); 123 fSettingsB = new BButton(rect, "settings", "Settings"B_UTF8_ELLIPSIS, 124 new BMessage(MSG_SETTINGS), 125 B_FOLLOW_LEFT | B_FOLLOW_BOTTOM, B_WILL_DRAW | B_NAVIGABLE); 126 fSettingsB->ResizeToPreferred(); 127 background->AddChild(fSettingsB); 128 fSettingsB->SetTarget(this); 129 130 textview->ResizeTo(fSettingsB->Frame().right - fFormatMF->Frame().left, 131 textview->Frame().Height()); 132 133 // Make sure the smallest window won't draw the "Settings" button over anything else 134 float minWindowWidth = textview->Bounds().Width() 135 + cancel->Bounds().Width() 136 + (insert ? insert->Bounds().Width() : 0.0) 137 + 90; 138 Window()->SetSizeLimits(minWindowWidth, 10000, 250, 10000); 139 if (Window()->Bounds().IntegerWidth() + 1 < minWindowWidth) 140 Window()->ResizeTo(minWindowWidth, Window()->Bounds().Height()); 141 142 143 window->Unlock(); 144 } 145 146 // destructor 147 SavePanel::~SavePanel() 148 { 149 } 150 151 // SendMessage 152 void 153 SavePanel::SendMessage(const BMessenger* messenger, BMessage* message) 154 { 155 // add the current format information to the message, 156 // bot only if we are indeed in export mode 157 if (message && fFormatM->IsEnabled()) 158 message->AddInt32("export mode", ExportMode()); 159 // let the original file panel code handle the rest 160 BFilePanel::SendMessage(messenger, message); 161 } 162 163 // MessageReceived 164 void 165 SavePanel::MessageReceived(BMessage* message) 166 { 167 // Handle messages from controls we've added 168 switch (message->what) { 169 case MSG_FORMAT: 170 fExportMode = ExportMode(); 171 AdjustExtension(); 172 // TODO: make this behaviour a setting 173 _EnableSettings(); 174 break; 175 case MSG_SETTINGS: 176 _ExportSettings(); 177 break; 178 default: 179 BHandler::MessageReceived(message); 180 break; 181 } 182 } 183 184 // SetExportMode 185 void 186 SavePanel::SetExportMode(bool exportMode) 187 { 188 BWindow* window = Window(); 189 if (!window || !window->Lock()) 190 return; 191 192 // adjust window title and enable format menu 193 BString helper("Icon-O-Matic: "); 194 if (exportMode) { 195 fFormatMF->SetEnabled(true); 196 SetExportMode(fExportMode); 197 _EnableSettings(); 198 helper << "Export Icon"; 199 } else { 200 fExportMode = ExportMode(); 201 // does not overwrite fExportMode in case we already were 202 // in native save mode 203 fNativeMI->SetMarked(true); 204 205 fFormatMF->SetEnabled(false); 206 fSettingsB->SetEnabled(false); 207 helper << "Save Icon"; 208 } 209 210 window->Unlock(); 211 } 212 213 // SetExportMode 214 void 215 SavePanel::SetExportMode(int32 mode) 216 { 217 BWindow* window = Window(); 218 if (!window || !window->Lock()) 219 return; 220 221 switch (mode) { 222 case EXPORT_MODE_MESSAGE: 223 fNativeMI->SetMarked(true); 224 break; 225 case EXPORT_MODE_FLAT_ICON: 226 fHVIFMI->SetMarked(true); 227 break; 228 case EXPORT_MODE_SVG: 229 fSVGMI->SetMarked(true); 230 break; 231 case EXPORT_MODE_BITMAP: 232 fBitmapMI->SetMarked(true); 233 break; 234 case EXPORT_MODE_BITMAP_SET: 235 fBitmapSetMI->SetMarked(true); 236 break; 237 case EXPORT_MODE_ICON_ATTR: 238 fIconAttrMI->SetMarked(true); 239 break; 240 case EXPORT_MODE_ICON_MIME_ATTR: 241 fIconMimeAttrMI->SetMarked(true); 242 break; 243 case EXPORT_MODE_ICON_RDEF: 244 fRDefMI->SetMarked(true); 245 break; 246 case EXPORT_MODE_ICON_SOURCE: 247 fSourceMI->SetMarked(true); 248 break; 249 } 250 251 if (mode != EXPORT_MODE_MESSAGE) 252 fExportMode = mode; 253 254 fFormatMF->SetEnabled(mode != EXPORT_MODE_MESSAGE); 255 _EnableSettings(); 256 257 window->Unlock(); 258 } 259 260 // ExportMode 261 int32 262 SavePanel::ExportMode() const 263 { 264 int32 mode = fExportMode; 265 BWindow* window = Window(); 266 if (!window || !window->Lock()) 267 return mode; 268 269 if (fFormatMF->IsEnabled()) { 270 // means we are actually in export mode 271 SaveItem* item = _GetCurrentMenuItem(); 272 mode = item->ExportMode(); 273 } 274 window->Unlock(); 275 276 return mode; 277 } 278 279 // AdjustExtension 280 void 281 SavePanel::AdjustExtension() 282 { 283 // if (!Window()->Lock()) 284 // return; 285 // 286 // BView* background = Window()->ChildAt(0); 287 // BTextControl* textview = dynamic_cast<BTextControl*>( 288 // background->FindView("text view")); 289 // 290 // if (textview) { 291 // 292 // translator_id id = 0; 293 // uint32 format = 0; 294 // int32 mode = ExportMode(); 295 // SaveItem* exportItem = dynamic_cast<SaveItem*>(_GetCurrentMenuItem()); 296 // if (mode == EXPORT_TRANSLATOR && exportItem) { 297 // id = exportItem->id; 298 // format = exportItem->format; 299 // } 300 // 301 // Exporter* exporter = Exporter::ExporterFor(mode, id, format); 302 // 303 // if (exporter) { 304 // BString name(textview->Text()); 305 // 306 // // adjust the name extension 307 // const char* extension = exporter->Extension(); 308 // if (strlen(extension) > 0) { 309 // int32 cutPos = name.FindLast('.'); 310 // int32 cutCount = name.Length() - cutPos; 311 // if (cutCount > 0 && cutCount <= 4) { 312 // name.Remove(cutPos, cutCount); 313 // } 314 // name << "." << extension; 315 // } 316 // 317 // SetSaveText(name.String()); 318 // } 319 // 320 // delete exporter; 321 // } 322 // Window()->Unlock(); 323 } 324 325 // _GetCurrentMenuItem 326 SaveItem* 327 SavePanel::_GetCurrentMenuItem() const 328 { 329 SaveItem* item = dynamic_cast<SaveItem*>(fFormatM->FindMarked()); 330 if (!item) 331 return fNativeMI; 332 return item; 333 } 334 335 // _ExportSettings 336 void 337 SavePanel::_ExportSettings() 338 { 339 // SaveItem *item = dynamic_cast<SaveItem*>(_GetCurrentMenuItem()); 340 // if (item == NULL) 341 // return; 342 // 343 // BTranslatorRoster *roster = BTranslatorRoster::Default(); 344 // BView *view; 345 // BRect rect(0, 0, 239, 239); 346 // 347 // // Build a window around this translator's configuration view 348 // status_t err = roster->MakeConfigurationView(item->id, NULL, &view, &rect); 349 // if (err < B_OK || view == NULL) { 350 // BAlert *alert = new BAlert(NULL, strerror(err), "OK"); 351 // alert->Go(); 352 // } else { 353 // if (fConfigWindow != NULL) { 354 // if (fConfigWindow->Lock()) 355 // fConfigWindow->Quit(); 356 // } 357 // fConfigWindow = new Panel(rect, "Translator Settings", 358 // B_TITLED_WINDOW_LOOK, 359 // B_NORMAL_WINDOW_FEEL, 360 // B_NOT_ZOOMABLE | B_NOT_RESIZABLE); 361 // fConfigWindow->AddChild(view); 362 // // Just to make sure 363 // view->MoveTo(0, 0); 364 // view->ResizeTo(rect.Width(), rect.Height()); 365 // view->ResizeToPreferred(); 366 // fConfigWindow->MoveTo(100, 100); 367 // fConfigWindow->Show(); 368 // } 369 } 370 371 // _BuildMenu 372 void 373 SavePanel::_BuildMenu() 374 { 375 fFormatM = new BPopUpMenu("Format"); 376 377 fNativeMI = new SaveItem("Icon-O-Matic", new BMessage(MSG_FORMAT), 378 EXPORT_MODE_MESSAGE); 379 fFormatM->AddItem(fNativeMI); 380 fNativeMI->SetEnabled(false); 381 382 fFormatM->AddSeparatorItem(); 383 384 fHVIFMI = new SaveItem("HVIF", new BMessage(MSG_FORMAT), 385 EXPORT_MODE_FLAT_ICON); 386 fFormatM->AddItem(fHVIFMI); 387 388 fRDefMI = new SaveItem("HVIF RDef", new BMessage(MSG_FORMAT), 389 EXPORT_MODE_ICON_RDEF); 390 fFormatM->AddItem(fRDefMI); 391 392 fSourceMI = new SaveItem("HVIF Source Code", new BMessage(MSG_FORMAT), 393 EXPORT_MODE_ICON_SOURCE); 394 fFormatM->AddItem(fSourceMI); 395 396 fFormatM->AddSeparatorItem(); 397 398 fSVGMI = new SaveItem("SVG", new BMessage(MSG_FORMAT), 399 EXPORT_MODE_SVG); 400 fFormatM->AddItem(fSVGMI); 401 402 fFormatM->AddSeparatorItem(); 403 404 fBitmapMI = new SaveItem("PNG", new BMessage(MSG_FORMAT), 405 EXPORT_MODE_BITMAP); 406 fFormatM->AddItem(fBitmapMI); 407 408 fBitmapSetMI = new SaveItem("PNG Set", new BMessage(MSG_FORMAT), 409 EXPORT_MODE_BITMAP_SET); 410 fFormatM->AddItem(fBitmapSetMI); 411 412 fFormatM->AddSeparatorItem(); 413 414 fIconAttrMI = new SaveItem("BEOS:ICON Attribute", new BMessage(MSG_FORMAT), 415 EXPORT_MODE_ICON_ATTR); 416 fFormatM->AddItem(fIconAttrMI); 417 418 fIconMimeAttrMI = new SaveItem("META:ICON Attribute", new BMessage(MSG_FORMAT), 419 EXPORT_MODE_ICON_MIME_ATTR); 420 fFormatM->AddItem(fIconMimeAttrMI); 421 422 423 fFormatM->SetTargetForItems(this); 424 425 // pick the RDef item in the list 426 fRDefMI->SetMarked(true); 427 } 428 429 // _EnableSettings 430 void 431 SavePanel::_EnableSettings() const 432 { 433 // no settings currently necessary 434 fSettingsB->SetEnabled(false); 435 } 436 437