1 /* ConfigViews - config views for the account, protocols, and filters 2 ** 3 ** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved. 4 */ 5 6 7 #include "ConfigViews.h" 8 #include "Account.h" 9 #include "CenterContainer.h" 10 11 #include <TextControl.h> 12 #include <ListView.h> 13 #include <ScrollView.h> 14 #include <PopUpMenu.h> 15 #include <MenuField.h> 16 #include <MenuItem.h> 17 #include <Button.h> 18 #include <Bitmap.h> 19 #include <Looper.h> 20 #include <Path.h> 21 #include <Alert.h> 22 #include <Entry.h> 23 #include <FindDirectory.h> 24 #include <Directory.h> 25 26 #include <string.h> 27 28 #include <MailSettings.h> 29 30 #include <MDRLanguage.h> 31 32 // AccountConfigView 33 const uint32 kMsgAccountTypeChanged = 'atch'; 34 const uint32 kMsgAccountNameChanged = 'anmc'; 35 36 // ProtocolsConfigView 37 const uint32 kMsgProtocolChanged = 'prch'; 38 39 // FiltersConfigView 40 const uint32 kMsgItemDragged = 'itdr'; 41 const uint32 kMsgFilterMoved = 'flmv'; 42 const uint32 kMsgChainSelected = 'chsl'; 43 const uint32 kMsgAddFilter = 'addf'; 44 const uint32 kMsgRemoveFilter = 'rmfi'; 45 const uint32 kMsgFilterSelected = 'fsel'; 46 47 48 AccountConfigView::AccountConfigView(BRect rect,Account *account) 49 : BBox(rect), 50 fAccount(account) 51 { 52 SetLabel(MDR_DIALECT_CHOICE ("Account Configuration","アカウント設定")); 53 54 rect = Bounds().InsetByCopy(8,8); 55 rect.top += 10; 56 CenterContainer *view = new CenterContainer(rect,false); 57 view->SetSpacing(5); 58 59 // determine font height 60 font_height fontHeight; 61 view->GetFontHeight(&fontHeight); 62 int32 height = (int32)(fontHeight.ascent + fontHeight.descent + fontHeight.leading) + 5; 63 64 rect = view->Bounds(); 65 rect.bottom = height + 5; 66 67 float labelWidth = view->StringWidth(MDR_DIALECT_CHOICE ("Account Name:","アカウント名:")) + 6; 68 69 view->AddChild(fNameControl = new BTextControl(rect,NULL,MDR_DIALECT_CHOICE ("Account Name:","アカウント名:"),NULL,new BMessage(kMsgAccountNameChanged))); 70 fNameControl->SetDivider(labelWidth); 71 view->AddChild(fRealNameControl = new BTextControl(rect,NULL,MDR_DIALECT_CHOICE ("Real Name:","名前 :"),NULL,NULL)); 72 fRealNameControl->SetDivider(labelWidth); 73 view->AddChild(fReturnAddressControl = new BTextControl(rect,NULL,MDR_DIALECT_CHOICE ("Return Address:","返信アドレス:"),NULL,NULL)); 74 fReturnAddressControl->SetDivider(labelWidth); 75 // control->TextView()->HideTyping(true); 76 77 BPopUpMenu *chainsPopUp = new BPopUpMenu(B_EMPTY_STRING); 78 const char *chainModes[] = { 79 MDR_DIALECT_CHOICE ("Inbound Only","受信のみ"), 80 MDR_DIALECT_CHOICE ("Outbound Only","送信のみ"), 81 MDR_DIALECT_CHOICE ("Inbound & Outbound","送受信")}; 82 BMenuItem *item; 83 for (int32 i = 0;i < 3;i++) 84 chainsPopUp->AddItem(item = new BMenuItem(chainModes[i],new BMessage(kMsgAccountTypeChanged))); 85 86 fTypeField = new BMenuField(rect,NULL,MDR_DIALECT_CHOICE ("Account Type:","用途 :"),chainsPopUp); 87 fTypeField->SetDivider(labelWidth + 3); 88 view->AddChild(fTypeField); 89 90 float w,h; 91 view->GetPreferredSize(&w,&h); 92 ResizeTo(w + 15,h + 22); 93 view->ResizeTo(w,h); 94 95 AddChild(view); 96 } 97 98 99 void AccountConfigView::DetachedFromWindow() 100 { 101 fAccount->SetName(fNameControl->Text()); 102 fAccount->SetRealName(fRealNameControl->Text()); 103 fAccount->SetReturnAddress(fReturnAddressControl->Text()); 104 } 105 106 107 void AccountConfigView::AttachedToWindow() 108 { 109 UpdateViews(); 110 fNameControl->SetTarget(this); 111 fTypeField->Menu()->SetTargetForItems(this); 112 } 113 114 115 void AccountConfigView::MessageReceived(BMessage *msg) 116 { 117 switch (msg->what) 118 { 119 case kMsgAccountTypeChanged: 120 { 121 int32 index; 122 if (msg->FindInt32("index",&index) < B_OK) 123 break; 124 125 if (fAccount->Type() < 0) 126 { 127 fNameControl->SetEnabled(true); 128 fRealNameControl->SetEnabled(true); 129 fReturnAddressControl->SetEnabled(true); 130 } 131 fAccount->SetType(index); 132 UpdateViews(); 133 break; 134 } 135 case kMsgAccountNameChanged: 136 fAccount->SetName(fNameControl->Text()); 137 break; 138 139 default: 140 BView::MessageReceived(msg); 141 } 142 } 143 144 145 void AccountConfigView::UpdateViews() 146 { 147 if (!fAccount->Inbound() && !fAccount->Outbound()) 148 { 149 if (BMenuItem *item = fTypeField->Menu()->FindMarked()) 150 item->SetMarked(false); 151 fTypeField->Menu()->Superitem()->SetLabel(MDR_DIALECT_CHOICE ("<select account type>","<用途を選択してください>")); 152 153 fNameControl->SetEnabled(false); 154 fRealNameControl->SetEnabled(false); 155 fReturnAddressControl->SetEnabled(false); 156 return; 157 } 158 fNameControl->SetText(fAccount->Name()); 159 fRealNameControl->SetText(fAccount->RealName()); 160 fReturnAddressControl->SetText(fAccount->ReturnAddress()); 161 162 if (BMenuItem *item = fTypeField->Menu()->ItemAt(fAccount->Type())) 163 item->SetMarked(true); 164 } 165 166 167 //--------------------------------------------------------------------------------------- 168 // #pragma mark - 169 170 #include <stdio.h> 171 FilterConfigView::FilterConfigView(BMailChain *chain,int32 index,BMessage *msg,entry_ref *ref) 172 : BBox(BRect(0,0,100,100)), 173 fConfigView(NULL), 174 fChain(chain), 175 fIndex(index), 176 fMessage(msg), 177 fEntryRef(ref) 178 { 179 Load(msg,ref); 180 BPath addon(ref); 181 SetLabel(addon.Leaf()); 182 } 183 184 185 FilterConfigView::~FilterConfigView() 186 { 187 Remove(); 188 } 189 190 191 void FilterConfigView::Load(BMessage *msg,entry_ref *ref) 192 { 193 ResizeTo(264,30); 194 195 BView *(* instantiate_config)(BMessage *,BMessage *); 196 BPath addon(ref); 197 fImage = load_add_on(addon.Path()); 198 if (fImage < B_OK) 199 return; 200 201 if (get_image_symbol(fImage,"instantiate_config_panel",B_SYMBOL_TYPE_TEXT,(void **)&instantiate_config) < B_OK) 202 { 203 unload_add_on(fImage); 204 fImage = B_MISSING_SYMBOL; 205 return; 206 } 207 208 fConfigView = (*instantiate_config)(msg,fChain->MetaData()); 209 210 float w = fConfigView->Bounds().Width(); 211 float h = fConfigView->Bounds().Height(); 212 fConfigView->MoveTo(3,13); 213 ResizeTo(w + 6,h + 16); 214 AddChild(fConfigView); 215 } 216 217 218 void FilterConfigView::Remove(bool deleteMessage) 219 { 220 // remove config view here, because they may not be available 221 // anymore, if the add-on is unloaded 222 if (fConfigView && RemoveChild(fConfigView)) 223 { 224 delete fConfigView; 225 fConfigView = NULL; 226 } 227 unload_add_on(fImage); 228 229 if (deleteMessage) 230 { 231 delete fMessage; 232 fMessage = NULL; 233 } 234 delete fEntryRef; 235 fEntryRef = NULL; 236 } 237 238 239 status_t FilterConfigView::InitCheck() 240 { 241 return fImage; 242 } 243 244 245 void FilterConfigView::DetachedFromWindow() 246 { 247 if (fConfigView == NULL) 248 return; 249 250 if (fConfigView->Archive(fMessage) >= B_OK) 251 fChain->SetFilter(fIndex,*fMessage,*fEntryRef); 252 } 253 254 255 void FilterConfigView::AttachedToWindow() 256 { 257 } 258 259 260 //--------------------------------------------------------------------------------------- 261 // #pragma mark - 262 263 264 ProtocolsConfigView::ProtocolsConfigView(BMailChain *chain,int32 index,BMessage *msg,entry_ref *ref) 265 : FilterConfigView(chain,index,msg,ref) 266 { 267 BPopUpMenu *menu = new BPopUpMenu("<choose protocol>"); 268 269 for (int i = 0; i < 2; i++) { 270 BPath path; 271 status_t status = find_directory((i == 0) ? B_USER_ADDONS_DIRECTORY : B_BEOS_ADDONS_DIRECTORY,&path); 272 if (status != B_OK) 273 { 274 fImage = status; 275 return; 276 } 277 278 path.Append("mail_daemon"); 279 280 if (chain->ChainDirection() == inbound) 281 path.Append("inbound_protocols"); 282 else 283 path.Append("outbound_protocols"); 284 285 BDirectory dir(path.Path()); 286 entry_ref protocolRef; 287 while (dir.GetNextRef(&protocolRef) == B_OK) 288 { 289 char name[B_FILE_NAME_LENGTH]; 290 BEntry entry(&protocolRef); 291 entry.GetName(name); 292 293 BMenuItem *item; 294 BMessage *msg; 295 menu->AddItem(item = new BMenuItem(name,msg = new BMessage(kMsgProtocolChanged))); 296 msg->AddRef("protocol",&protocolRef); 297 298 if (*ref == protocolRef) 299 item->SetMarked(true); 300 } 301 } 302 303 fProtocolsMenuField = new BMenuField(BRect(0,0,200,40),NULL,NULL,menu); 304 fProtocolsMenuField->ResizeToPreferred(); 305 SetLabel(fProtocolsMenuField); 306 307 if (fConfigView) 308 { 309 fConfigView->MoveTo(3,21); 310 ResizeBy(0,8); 311 } 312 else 313 fImage = B_OK; 314 } 315 316 317 void ProtocolsConfigView::AttachedToWindow() 318 { 319 FilterConfigView::AttachedToWindow(); 320 fProtocolsMenuField->Menu()->SetTargetForItems(this); 321 } 322 323 324 void ProtocolsConfigView::MessageReceived(BMessage *msg) 325 { 326 switch (msg->what) 327 { 328 case kMsgProtocolChanged: 329 { 330 entry_ref ref; 331 if (msg->FindRef("protocol",&ref) < B_OK) 332 break; 333 334 DetachedFromWindow(); 335 Remove(false); 336 337 fEntryRef = new entry_ref(ref); 338 Load(fMessage,fEntryRef); 339 fChain->SetFilter(fIndex,*fMessage,*fEntryRef); 340 341 // resize view 342 if (LockLooperWithTimeout(1000000L) == B_OK) 343 { 344 if (fConfigView) 345 { 346 fConfigView->MoveTo(3,21); 347 ResizeBy(0,8); 348 } 349 UnlockLooper(); 350 351 if (CenterContainer *container = dynamic_cast<CenterContainer *>(Parent())) 352 container->Layout(); 353 } 354 break; 355 } 356 default: 357 BView::MessageReceived(msg); 358 break; 359 } 360 } 361 362 363 //--------------------------------------------------------------------------------------- 364 // #pragma mark - 365 366 #include <stdio.h> 367 class DragListView : public BListView 368 { 369 public: 370 DragListView(BRect frame,const char *name,list_view_type type = B_SINGLE_SELECTION_LIST, 371 uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP,BMessage *itemMovedMsg = NULL) 372 : BListView(frame,name,type,resizingMode), 373 fDragging(false), 374 fItemMovedMessage(itemMovedMsg) 375 { 376 } 377 378 virtual bool InitiateDrag(BPoint point,int32 index,bool wasSelected) 379 { 380 BRect frame(ItemFrame(index)); 381 BBitmap *bitmap = new BBitmap(frame.OffsetToCopy(B_ORIGIN),B_RGBA32,true); 382 BView *view = new BView(bitmap->Bounds(),NULL,0,0); 383 bitmap->AddChild(view); 384 385 if (view->LockLooper()) 386 { 387 BListItem *item = ItemAt(index); 388 bool selected = item->IsSelected(); 389 390 view->SetLowColor(225,225,225,128); 391 view->FillRect(view->Bounds()); 392 393 if (selected) 394 item->Deselect(); 395 ItemAt(index)->DrawItem(view,view->Bounds(),true); 396 if (selected) 397 item->Select(); 398 399 view->UnlockLooper(); 400 } 401 fLastDragTarget = -1; 402 fDragIndex = index; 403 fDragging = true; 404 405 BMessage drag(kMsgItemDragged); 406 drag.AddInt32("index",index); 407 DragMessage(&drag,bitmap,B_OP_ALPHA,point - frame.LeftTop(),this); 408 409 return true; 410 } 411 412 void DrawDragTargetIndicator(int32 target) 413 { 414 PushState(); 415 SetDrawingMode(B_OP_INVERT); 416 417 bool last = false; 418 if (target >= CountItems()) 419 target = CountItems() - 1, last = true; 420 421 BRect frame = ItemFrame(target); 422 if (last) 423 frame.OffsetBy(0,frame.Height()); 424 frame.bottom = frame.top + 1; 425 426 FillRect(frame); 427 428 PopState(); 429 } 430 431 virtual void MouseMoved(BPoint point,uint32 transit,const BMessage *msg) 432 { 433 BListView::MouseMoved(point,transit,msg); 434 435 if ((transit != B_ENTERED_VIEW && transit != B_INSIDE_VIEW) || !fDragging) 436 return; 437 438 int32 target = IndexOf(point); 439 if (target == -1) 440 target = CountItems(); 441 442 // correct the target insertion index 443 if (target == fDragIndex || target == fDragIndex + 1) 444 target = -1; 445 446 if (target == fLastDragTarget) 447 return; 448 449 // remove old target indicator 450 if (fLastDragTarget != -1) 451 DrawDragTargetIndicator(fLastDragTarget); 452 453 // draw new one 454 fLastDragTarget = target; 455 if (target != -1) 456 DrawDragTargetIndicator(target); 457 } 458 459 virtual void MouseUp(BPoint point) 460 { 461 if (fDragging) 462 { 463 fDragging = false; 464 if (fLastDragTarget != -1) 465 DrawDragTargetIndicator(fLastDragTarget); 466 } 467 BListView::MouseUp(point); 468 } 469 470 virtual void MessageReceived(BMessage *msg) 471 { 472 switch(msg->what) 473 { 474 case kMsgItemDragged: 475 { 476 int32 source = msg->FindInt32("index"); 477 BPoint point = msg->FindPoint("_drop_point_"); 478 ConvertFromScreen(&point); 479 int32 to = IndexOf(point); 480 if (to > fDragIndex) 481 to--; 482 if (to == -1) 483 to = CountItems() - 1; 484 485 if (source != to) 486 { 487 MoveItem(source,to); 488 489 if (fItemMovedMessage != NULL) 490 { 491 BMessage msg(fItemMovedMessage->what); 492 msg.AddInt32("from",source); 493 msg.AddInt32("to",to); 494 Messenger().SendMessage(&msg); 495 } 496 } 497 break; 498 } 499 } 500 BListView::MessageReceived(msg); 501 } 502 503 private: 504 bool fDragging; 505 int32 fLastDragTarget,fDragIndex; 506 BMessage *fItemMovedMessage; 507 }; 508 509 510 void GetPrettyDescriptiveName(BPath &path, char *name, BMessage *msg = NULL) 511 { 512 strcpy(name, path.Leaf()); 513 514 image_id image = load_add_on(path.Path()); 515 if (image < B_OK) 516 return; 517 518 if (msg) 519 { 520 status_t (* descriptive_name)(BMessage *,char *); 521 if (get_image_symbol(image,"descriptive_name",B_SYMBOL_TYPE_TEXT,(void **)&descriptive_name) == B_OK) 522 (*descriptive_name)(msg,name); 523 } 524 unload_add_on(image); 525 } 526 527 528 // #pragma mark - 529 530 531 FiltersConfigView::FiltersConfigView(BRect rect,Account *account) 532 : BBox(rect), 533 fAccount(account), 534 fFilterView(NULL) 535 { 536 BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING); 537 538 BMenuItem *item; 539 BMessage *msg; 540 if ((fChain = fAccount->Inbound())) 541 { 542 menu->AddItem(item = new BMenuItem(MDR_DIALECT_CHOICE ("Incoming E-mail Filters","受信フィルタ"),msg = new BMessage(kMsgChainSelected))); 543 msg->AddPointer("chain",fChain); 544 item->SetMarked(true); 545 } 546 if (BMailChain *chain = fAccount->Outbound()) 547 { 548 menu->AddItem(item = new BMenuItem(MDR_DIALECT_CHOICE ("Outgoing E-mail Filters","送信フィルタ"),msg = new BMessage(kMsgChainSelected))); 549 msg->AddPointer("chain",chain); 550 if (fChain == NULL) 551 { 552 item->SetMarked(true); 553 fChain = chain; 554 } 555 } 556 557 fChainsField = new BMenuField(BRect(0,0,200,40),NULL,NULL,menu); 558 fChainsField->ResizeToPreferred(); 559 SetLabel(fChainsField); 560 561 // determine font height 562 font_height fontHeight; 563 fChainsField->GetFontHeight(&fontHeight); 564 int32 height = (int32)(fontHeight.ascent + fontHeight.descent + fontHeight.leading) + 5; 565 566 rect = Bounds().InsetByCopy(10,10); 567 rect.top += 18; 568 rect.right -= B_V_SCROLL_BAR_WIDTH; 569 rect.bottom = rect.top + 4 * height + 2; 570 fListView = new DragListView(rect,NULL,B_SINGLE_SELECTION_LIST,B_FOLLOW_ALL,new BMessage(kMsgFilterMoved)); 571 AddChild(new BScrollView(NULL,fListView,B_FOLLOW_ALL,0,false,true)); 572 rect.right += B_V_SCROLL_BAR_WIDTH; 573 574 // fListView->Select(gSettings.formats.IndexOf(format)); 575 fListView->SetSelectionMessage(new BMessage(kMsgFilterSelected)); 576 577 rect.top = rect.bottom + 8; rect.bottom = rect.top + height; 578 BRect sizeRect = rect; sizeRect.right = sizeRect.left + 30 + fChainsField->StringWidth(MDR_DIALECT_CHOICE ("Add Filter","フィルタの追加")); 579 580 menu = new BPopUpMenu(MDR_DIALECT_CHOICE ("Add Filter","フィルタの追加")); 581 menu->SetRadioMode(false); 582 583 fAddField = new BMenuField(rect,NULL,NULL,menu); 584 fAddField->ResizeToPreferred(); 585 AddChild(fAddField); 586 587 sizeRect.left = sizeRect.right + 5; sizeRect.right = sizeRect.left + 30 + fChainsField->StringWidth(MDR_DIALECT_CHOICE ("Remove","削除")); 588 sizeRect.top--; 589 AddChild(fRemoveButton = new BButton(sizeRect,NULL,MDR_DIALECT_CHOICE ("Remove","削除"),new BMessage(kMsgRemoveFilter),B_FOLLOW_BOTTOM)); 590 591 ResizeTo(Bounds().Width(),sizeRect.bottom + 10); 592 SetTo(fChain); 593 } 594 595 596 FiltersConfigView::~FiltersConfigView() 597 { 598 } 599 600 601 void FiltersConfigView::SelectFilter(int32 index) 602 { 603 if (Parent()) 604 Parent()->Hide(); 605 606 // remove old config view 607 if (fFilterView) 608 { 609 Parent()->RemoveChild(fFilterView); 610 611 // update the name in the list 612 BStringItem *item = (BStringItem *)fListView->ItemAt(fFilterView->fIndex - fFirst); 613 614 char name[B_FILE_NAME_LENGTH]; 615 BPath path(fFilterView->fEntryRef); 616 GetPrettyDescriptiveName(path, name, fFilterView->fMessage); 617 item->SetText(name); 618 619 delete fFilterView; 620 fFilterView = NULL; 621 } 622 623 if (index >= 0) 624 { 625 // add new config view 626 BMessage *msg = new BMessage(); 627 entry_ref *ref = new entry_ref(); 628 if (fChain->GetFilter(index + fFirst,msg,ref) >= B_OK && Parent()) 629 { 630 fFilterView = new FilterConfigView(fChain,index + fFirst,msg,ref); 631 if (fFilterView->InitCheck() >= B_OK) 632 Parent()->AddChild(fFilterView); 633 else 634 { 635 delete fFilterView; 636 fFilterView = NULL; 637 } 638 } 639 else 640 { 641 delete msg; 642 delete ref; 643 } 644 } 645 646 // re-layout the view containing the config view 647 if (CenterContainer *container = dynamic_cast<CenterContainer *>(Parent())) 648 container->Layout(); 649 650 if (Parent()) 651 Parent()->Show(); 652 } 653 654 655 void FiltersConfigView::SetTo(BMailChain *chain) 656 { 657 // remove the filter config view 658 SelectFilter(-1); 659 660 for (int32 i = fListView->CountItems();i-- > 0;) 661 { 662 BStringItem *item = (BStringItem *)fListView->RemoveItem(i); 663 delete item; 664 } 665 666 if (chain->ChainDirection() == inbound) 667 { 668 fFirst = 2; // skip protocol (e.g. POP3), and Parser 669 fLast = 2; // skip Notifier, and Folder 670 } 671 else 672 { 673 fFirst = 1; // skip Producer 674 fLast = 1; // skip protocol (e.g. SMTP) 675 } 676 int32 last = chain->CountFilters() - fLast; 677 for (int32 i = fFirst;i < last;i++) 678 { 679 BMessage msg; 680 entry_ref ref; 681 if (chain->GetFilter(i,&msg,&ref) == B_OK) 682 { 683 char name[B_FILE_NAME_LENGTH]; 684 BPath addon(&ref); 685 GetPrettyDescriptiveName(addon, name, &msg); 686 687 fListView->AddItem(new BStringItem(name)); 688 } 689 } 690 fChain = chain; 691 692 /*** search inbound/outbound filters ***/ 693 694 // remove old filter items 695 BMenu *menu = fAddField->Menu(); 696 for (int32 i = menu->CountItems();i-- > 0;) 697 { 698 BMenuItem *item = menu->RemoveItem(i); 699 delete item; 700 } 701 702 for (int i = 0; i < 2; i++) { 703 BPath path; 704 status_t status = find_directory((i == 0) ? B_USER_ADDONS_DIRECTORY : B_BEOS_ADDONS_DIRECTORY,&path); 705 if (status != B_OK) 706 return; 707 708 path.Append("mail_daemon"); 709 710 if (fChain->ChainDirection() == inbound) 711 path.Append("inbound_filters"); 712 else 713 path.Append("outbound_filters"); 714 715 BDirectory dir(path.Path()); 716 entry_ref ref; 717 while (dir.GetNextRef(&ref) == B_OK) 718 { 719 char name[B_FILE_NAME_LENGTH]; 720 BPath path(&ref); 721 GetPrettyDescriptiveName(path, name); 722 723 BMenuItem *item; 724 BMessage *msg; 725 menu->AddItem(item = new BMenuItem(name,msg = new BMessage(kMsgAddFilter))); 726 msg->AddRef("filter",&ref); 727 } 728 } 729 menu->SetTargetForItems(this); 730 } 731 732 733 void FiltersConfigView::AttachedToWindow() 734 { 735 fChainsField->Menu()->SetTargetForItems(this); 736 fListView->SetTarget(this); 737 fAddField->Menu()->SetTargetForItems(this); 738 fRemoveButton->SetTarget(this); 739 } 740 741 742 void FiltersConfigView::MessageReceived(BMessage *msg) 743 { 744 switch (msg->what) 745 { 746 case kMsgChainSelected: 747 { 748 BMailChain *chain; 749 if (msg->FindPointer("chain",(void **)&chain) < B_OK) 750 break; 751 752 SetTo(chain); 753 break; 754 } 755 case kMsgAddFilter: 756 { 757 entry_ref ref; 758 if (msg->FindRef("filter",&ref) < B_OK) 759 break; 760 761 BMessage msg; 762 if (fChain->AddFilter(fChain->CountFilters() - fLast, msg, ref) >= B_OK) 763 { 764 char name[B_FILE_NAME_LENGTH]; 765 BPath path(&ref); 766 GetPrettyDescriptiveName(path, name, &msg); 767 fListView->AddItem(new BStringItem(name)); 768 } 769 break; 770 } 771 case kMsgRemoveFilter: 772 { 773 int32 index = fListView->CurrentSelection(); 774 if (index < 0) 775 break; 776 777 SelectFilter(-1); 778 if (BStringItem *item = (BStringItem *)fListView->RemoveItem(index)) 779 { 780 fChain->RemoveFilter(index + fFirst); 781 delete item; 782 } 783 break; 784 } 785 case kMsgFilterSelected: 786 { 787 int32 index; 788 if (msg->FindInt32("index",&index) < B_OK) 789 break; 790 791 SelectFilter(index); 792 break; 793 } 794 case kMsgFilterMoved: 795 { 796 int32 from = msg->FindInt32("from"); 797 int32 to = msg->FindInt32("to"); 798 if (from == to) 799 break; 800 801 from += fFirst; 802 to += fFirst; 803 804 entry_ref ref; 805 BMessage settings; 806 if (fChain->GetFilter(from,&settings,&ref) == B_OK) 807 { 808 // disable filter view saving 809 if (fFilterView && fFilterView->fIndex == from) 810 fFilterView->fIndex = -1; 811 812 fChain->RemoveFilter(from); 813 814 if (fChain->AddFilter(to,settings,ref) < B_OK) 815 { 816 (new BAlert("E-mail",MDR_DIALECT_CHOICE ( 817 "Could not move filter, filter deleted.", 818 "フィルタが削除された為、移動できません"),"Ok"))->Go(); 819 820 // the filter view belongs to the moved filter 821 if (fFilterView && fFilterView->fIndex == -1) 822 SelectFilter(-1); 823 824 fListView->RemoveItem(msg->FindInt32("to")); 825 } 826 else if (fFilterView) 827 { 828 int32 index = fFilterView->fIndex; 829 if (index == -1) 830 // the view belongs to the moved filter 831 fFilterView->fIndex = to; 832 else if (index > from && index < to) 833 // the view belongs to another filter (between the 834 // 'from' & 'to' positions) - all others can keep 835 // their index value 836 fFilterView->fIndex--; 837 } 838 } 839 break; 840 } 841 default: 842 BView::MessageReceived(msg); 843 break; 844 } 845 } 846 847