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 } 247 248 if (mode != EXPORT_MODE_MESSAGE) 249 fExportMode = mode; 250 251 fFormatMF->SetEnabled(mode != EXPORT_MODE_MESSAGE); 252 _EnableSettings(); 253 254 window->Unlock(); 255 } 256 257 // ExportMode 258 int32 259 SavePanel::ExportMode() const 260 { 261 int32 mode = fExportMode; 262 BWindow* window = Window(); 263 if (!window || !window->Lock()) 264 return mode; 265 266 if (fFormatMF->IsEnabled()) { 267 // means we are actually in export mode 268 SaveItem* item = _GetCurrentMenuItem(); 269 mode = item->ExportMode(); 270 } 271 window->Unlock(); 272 273 return mode; 274 } 275 276 // AdjustExtension 277 void 278 SavePanel::AdjustExtension() 279 { 280 // if (!Window()->Lock()) 281 // return; 282 // 283 // BView* background = Window()->ChildAt(0); 284 // BTextControl* textview = dynamic_cast<BTextControl*>( 285 // background->FindView("text view")); 286 // 287 // if (textview) { 288 // 289 // translator_id id = 0; 290 // uint32 format = 0; 291 // int32 mode = ExportMode(); 292 // SaveItem* exportItem = dynamic_cast<SaveItem*>(_GetCurrentMenuItem()); 293 // if (mode == EXPORT_TRANSLATOR && exportItem) { 294 // id = exportItem->id; 295 // format = exportItem->format; 296 // } 297 // 298 // Exporter* exporter = Exporter::ExporterFor(mode, id, format); 299 // 300 // if (exporter) { 301 // BString name(textview->Text()); 302 // 303 // // adjust the name extension 304 // const char* extension = exporter->Extension(); 305 // if (strlen(extension) > 0) { 306 // int32 cutPos = name.FindLast('.'); 307 // int32 cutCount = name.Length() - cutPos; 308 // if (cutCount > 0 && cutCount <= 4) { 309 // name.Remove(cutPos, cutCount); 310 // } 311 // name << "." << extension; 312 // } 313 // 314 // SetSaveText(name.String()); 315 // } 316 // 317 // delete exporter; 318 // } 319 // Window()->Unlock(); 320 } 321 322 // _GetCurrentMenuItem 323 SaveItem* 324 SavePanel::_GetCurrentMenuItem() const 325 { 326 SaveItem* item = dynamic_cast<SaveItem*>(fFormatM->FindMarked()); 327 if (!item) 328 return fNativeMI; 329 return item; 330 } 331 332 // _ExportSettings 333 void 334 SavePanel::_ExportSettings() 335 { 336 // SaveItem *item = dynamic_cast<SaveItem*>(_GetCurrentMenuItem()); 337 // if (item == NULL) 338 // return; 339 // 340 // BTranslatorRoster *roster = BTranslatorRoster::Default(); 341 // BView *view; 342 // BRect rect(0, 0, 239, 239); 343 // 344 // // Build a window around this translator's configuration view 345 // status_t err = roster->MakeConfigurationView(item->id, NULL, &view, &rect); 346 // if (err < B_OK || view == NULL) { 347 // BAlert *alert = new BAlert(NULL, strerror(err), "OK"); 348 // alert->Go(); 349 // } else { 350 // if (fConfigWindow != NULL) { 351 // if (fConfigWindow->Lock()) 352 // fConfigWindow->Quit(); 353 // } 354 // fConfigWindow = new Panel(rect, "Translator Settings", 355 // B_TITLED_WINDOW_LOOK, 356 // B_NORMAL_WINDOW_FEEL, 357 // B_NOT_ZOOMABLE | B_NOT_RESIZABLE); 358 // fConfigWindow->AddChild(view); 359 // // Just to make sure 360 // view->MoveTo(0, 0); 361 // view->ResizeTo(rect.Width(), rect.Height()); 362 // view->ResizeToPreferred(); 363 // fConfigWindow->MoveTo(100, 100); 364 // fConfigWindow->Show(); 365 // } 366 } 367 368 // _BuildMenu 369 void 370 SavePanel::_BuildMenu() 371 { 372 fFormatM = new BPopUpMenu("Format"); 373 374 fNativeMI = new SaveItem("Icon-O-Matic", new BMessage(MSG_FORMAT), 375 EXPORT_MODE_MESSAGE); 376 fFormatM->AddItem(fNativeMI); 377 fNativeMI->SetEnabled(false); 378 379 fFormatM->AddSeparatorItem(); 380 381 fHVIFMI = new SaveItem("HVIF", new BMessage(MSG_FORMAT), 382 EXPORT_MODE_FLAT_ICON); 383 fFormatM->AddItem(fHVIFMI); 384 385 fRDefMI = new SaveItem("HVIF RDef", new BMessage(MSG_FORMAT), 386 EXPORT_MODE_ICON_RDEF); 387 fFormatM->AddItem(fRDefMI); 388 389 fFormatM->AddSeparatorItem(); 390 391 fSVGMI = new SaveItem("SVG", new BMessage(MSG_FORMAT), 392 EXPORT_MODE_SVG); 393 fFormatM->AddItem(fSVGMI); 394 395 fFormatM->AddSeparatorItem(); 396 397 fBitmapMI = new SaveItem("PNG", new BMessage(MSG_FORMAT), 398 EXPORT_MODE_BITMAP); 399 fFormatM->AddItem(fBitmapMI); 400 401 fBitmapSetMI = new SaveItem("PNG Set", new BMessage(MSG_FORMAT), 402 EXPORT_MODE_BITMAP_SET); 403 fFormatM->AddItem(fBitmapSetMI); 404 405 fFormatM->AddSeparatorItem(); 406 407 fIconAttrMI = new SaveItem("BEOS:ICON Attribute", new BMessage(MSG_FORMAT), 408 EXPORT_MODE_ICON_ATTR); 409 fFormatM->AddItem(fIconAttrMI); 410 411 fIconMimeAttrMI = new SaveItem("META:ICON Attribute", new BMessage(MSG_FORMAT), 412 EXPORT_MODE_ICON_MIME_ATTR); 413 fFormatM->AddItem(fIconMimeAttrMI); 414 415 416 fFormatM->SetTargetForItems(this); 417 418 // pick the RDef item in the list 419 fRDefMI->SetMarked(true); 420 } 421 422 // _EnableSettings 423 void 424 SavePanel::_EnableSettings() const 425 { 426 // no settings currently necessary 427 fSettingsB->SetEnabled(false); 428 } 429 430