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 // TODO: make this behaviour a setting 171 AdjustExtension(); 172 _EnableSettings(); 173 break; 174 case MSG_SETTINGS: 175 _ExportSettings(); 176 break; 177 default: 178 BHandler::MessageReceived(message); 179 break; 180 } 181 } 182 183 // SetExportMode 184 void 185 SavePanel::SetExportMode(bool exportMode) 186 { 187 BWindow* window = Window(); 188 if (!window || !window->Lock()) 189 return; 190 191 // adjust window title and enable format menu 192 BString helper("Icon-O-Matic: "); 193 if (exportMode) { 194 fFormatMF->SetEnabled(true); 195 SetExportMode(fExportMode); 196 _EnableSettings(); 197 helper << "Export Icon"; 198 } else { 199 fExportMode = ExportMode(); 200 // does not overwrite fExportMode in case we already were 201 // in native save mode 202 fNativeMI->SetMarked(true); 203 204 fFormatMF->SetEnabled(false); 205 fSettingsB->SetEnabled(false); 206 helper << "Save Icon"; 207 } 208 209 window->Unlock(); 210 } 211 212 // SetExportMode 213 void 214 SavePanel::SetExportMode(int32 mode) 215 { 216 BWindow* window = Window(); 217 if (!window || !window->Lock()) 218 return; 219 220 switch (mode) { 221 case EXPORT_MODE_MESSAGE: 222 fNativeMI->SetMarked(true); 223 break; 224 case EXPORT_MODE_FLAT_ICON: 225 fHVIFMI->SetMarked(true); 226 break; 227 case EXPORT_MODE_SVG: 228 fSVGMI->SetMarked(true); 229 break; 230 case EXPORT_MODE_BITMAP: 231 fBitmapMI->SetMarked(true); 232 break; 233 case EXPORT_MODE_BITMAP_SET: 234 fBitmapSetMI->SetMarked(true); 235 break; 236 case EXPORT_MODE_ICON_ATTR: 237 fIconAttrMI->SetMarked(true); 238 break; 239 case EXPORT_MODE_ICON_MIME_ATTR: 240 fIconMimeAttrMI->SetMarked(true); 241 break; 242 case EXPORT_MODE_ICON_RDEF: 243 fRDefMI->SetMarked(true); 244 break; 245 } 246 247 if (mode != EXPORT_MODE_MESSAGE) 248 fExportMode = mode; 249 250 fFormatMF->SetEnabled(mode != EXPORT_MODE_MESSAGE); 251 _EnableSettings(); 252 253 window->Unlock(); 254 } 255 256 // ExportMode 257 int32 258 SavePanel::ExportMode() const 259 { 260 int32 mode = fExportMode; 261 BWindow* window = Window(); 262 if (!window || !window->Lock()) 263 return mode; 264 265 if (fFormatMF->IsEnabled()) { 266 // means we are actually in export mode 267 SaveItem* item = _GetCurrentMenuItem(); 268 mode = item->ExportMode(); 269 } 270 window->Unlock(); 271 272 return mode; 273 } 274 275 // AdjustExtension 276 void 277 SavePanel::AdjustExtension() 278 { 279 // if (!Window()->Lock()) 280 // return; 281 // 282 // BView* background = Window()->ChildAt(0); 283 // BTextControl* textview = dynamic_cast<BTextControl*>( 284 // background->FindView("text view")); 285 // 286 // if (textview) { 287 // 288 // translator_id id = 0; 289 // uint32 format = 0; 290 // int32 mode = ExportMode(); 291 // SaveItem* exportItem = dynamic_cast<SaveItem*>(_GetCurrentMenuItem()); 292 // if (mode == EXPORT_TRANSLATOR && exportItem) { 293 // id = exportItem->id; 294 // format = exportItem->format; 295 // } 296 // 297 // Exporter* exporter = Exporter::ExporterFor(mode, id, format); 298 // 299 // if (exporter) { 300 // BString name(textview->Text()); 301 // 302 // // adjust the name extension 303 // const char* extension = exporter->Extension(); 304 // if (strlen(extension) > 0) { 305 // int32 cutPos = name.FindLast('.'); 306 // int32 cutCount = name.Length() - cutPos; 307 // if (cutCount > 0 && cutCount <= 4) { 308 // name.Remove(cutPos, cutCount); 309 // } 310 // name << "." << extension; 311 // } 312 // 313 // SetSaveText(name.String()); 314 // } 315 // 316 // delete exporter; 317 // } 318 // Window()->Unlock(); 319 } 320 321 // _GetCurrentMenuItem 322 SaveItem* 323 SavePanel::_GetCurrentMenuItem() const 324 { 325 SaveItem* item = dynamic_cast<SaveItem*>(fFormatM->FindMarked()); 326 if (!item) 327 return fNativeMI; 328 return item; 329 } 330 331 // _ExportSettings 332 void 333 SavePanel::_ExportSettings() 334 { 335 // SaveItem *item = dynamic_cast<SaveItem*>(_GetCurrentMenuItem()); 336 // if (item == NULL) 337 // return; 338 // 339 // BTranslatorRoster *roster = BTranslatorRoster::Default(); 340 // BView *view; 341 // BRect rect(0, 0, 239, 239); 342 // 343 // // Build a window around this translator's configuration view 344 // status_t err = roster->MakeConfigurationView(item->id, NULL, &view, &rect); 345 // if (err < B_OK || view == NULL) { 346 // BAlert *alert = new BAlert(NULL, strerror(err), "OK"); 347 // alert->Go(); 348 // } else { 349 // if (fConfigWindow != NULL) { 350 // if (fConfigWindow->Lock()) 351 // fConfigWindow->Quit(); 352 // } 353 // fConfigWindow = new Panel(rect, "Translator Settings", 354 // B_TITLED_WINDOW_LOOK, 355 // B_NORMAL_WINDOW_FEEL, 356 // B_NOT_ZOOMABLE | B_NOT_RESIZABLE); 357 // fConfigWindow->AddChild(view); 358 // // Just to make sure 359 // view->MoveTo(0, 0); 360 // view->ResizeTo(rect.Width(), rect.Height()); 361 // view->ResizeToPreferred(); 362 // fConfigWindow->MoveTo(100, 100); 363 // fConfigWindow->Show(); 364 // } 365 } 366 367 // _BuildMenu 368 void 369 SavePanel::_BuildMenu() 370 { 371 fFormatM = new BPopUpMenu("Format"); 372 373 fNativeMI = new SaveItem("Icon-O-Matic", new BMessage(MSG_FORMAT), 374 EXPORT_MODE_MESSAGE); 375 fFormatM->AddItem(fNativeMI); 376 fNativeMI->SetEnabled(false); 377 378 fFormatM->AddSeparatorItem(); 379 380 fHVIFMI = new SaveItem("HVIF", new BMessage(MSG_FORMAT), 381 EXPORT_MODE_FLAT_ICON); 382 fFormatM->AddItem(fHVIFMI); 383 384 fRDefMI = new SaveItem("HVIF RDef", new BMessage(MSG_FORMAT), 385 EXPORT_MODE_ICON_RDEF); 386 fFormatM->AddItem(fRDefMI); 387 388 fFormatM->AddSeparatorItem(); 389 390 fSVGMI = new SaveItem("SVG", new BMessage(MSG_FORMAT), 391 EXPORT_MODE_SVG); 392 fFormatM->AddItem(fSVGMI); 393 394 fFormatM->AddSeparatorItem(); 395 396 fBitmapMI = new SaveItem("PNG", new BMessage(MSG_FORMAT), 397 EXPORT_MODE_BITMAP); 398 fFormatM->AddItem(fBitmapMI); 399 400 fBitmapSetMI = new SaveItem("PNG Set", new BMessage(MSG_FORMAT), 401 EXPORT_MODE_BITMAP_SET); 402 fFormatM->AddItem(fBitmapSetMI); 403 404 fFormatM->AddSeparatorItem(); 405 406 fIconAttrMI = new SaveItem("BEOS:ICON Attribute", new BMessage(MSG_FORMAT), 407 EXPORT_MODE_ICON_ATTR); 408 fFormatM->AddItem(fIconAttrMI); 409 410 fIconMimeAttrMI = new SaveItem("META:ICON Attribute", new BMessage(MSG_FORMAT), 411 EXPORT_MODE_ICON_MIME_ATTR); 412 fFormatM->AddItem(fIconMimeAttrMI); 413 414 415 fFormatM->SetTargetForItems(this); 416 417 // pick the RDef item in the list 418 fRDefMI->SetMarked(true); 419 } 420 421 // _EnableSettings 422 void 423 SavePanel::_EnableSettings() const 424 { 425 // no settings currently necessary 426 fSettingsB->SetEnabled(false); 427 } 428 429