RemoteDrawingEngine: Reduce RP_READ_BITMAP result timeout.
[haiku.git] / src / apps / mail / Header.cpp
blob5745511eedabdc0aec5c34f6bd1a8816800f6975
1 /*
2 Open Tracker License
4 Terms and Conditions
6 Copyright (c) 1991-2001, Be Incorporated. All rights reserved.
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN
23 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
29 BeMail(TM), Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or
30 registered trademarks of Be Incorporated in the United States and other
31 countries. Other brand product names are registered trademarks or trademarks
32 of their respective holders. All rights reserved.
36 #include "Header.h"
38 #include <stdio.h>
40 #include <ControlLook.h>
41 #include <DateTimeFormat.h>
42 #include <E-mail.h>
43 #include <LayoutBuilder.h>
44 #include <Locale.h>
45 #include <MenuBar.h>
46 #include <MenuField.h>
47 #include <MenuItem.h>
48 #include <ObjectList.h>
49 #include <PopUpMenu.h>
50 #include <Query.h>
51 #include <String.h>
52 #include <StringView.h>
53 #include <Volume.h>
54 #include <VolumeRoster.h>
55 #include <Window.h>
56 #include <fs_index.h>
57 #include <fs_info.h>
59 #include <MailSettings.h>
60 #include <MailMessage.h>
62 #include "MailApp.h"
63 #include "MailSupport.h"
64 #include "MailWindow.h"
65 #include "Messages.h"
66 #include "Utilities.h"
67 #include "QueryMenu.h"
68 #include "FieldMsg.h"
69 #include "Prefs.h"
72 #define B_TRANSLATION_CONTEXT "Mail"
75 using namespace BPrivate;
76 using std::map;
79 const uint32 kMsgFrom = 'hFrm';
80 const uint32 kMsgAddressChosen = 'acsn';
83 struct CompareBStrings {
84 bool
85 operator()(const BString *s1, const BString *s2) const
87 return (s1->Compare(*s2) < 0);
92 class LabelView : public BStringView {
93 public:
94 LabelView(const char* label);
96 bool IsEnabled() const
97 { return fEnabled; }
98 void SetEnabled(bool enabled);
100 virtual void Draw(BRect updateRect);
102 private:
103 bool fEnabled;
107 class HeaderTextControl : public BTextControl {
108 public:
109 HeaderTextControl(const char* label,
110 const char* name, BMessage* message);
112 virtual void AttachedToWindow();
113 virtual void SetEnabled(bool enabled);
114 virtual void Draw(BRect updateRect);
115 virtual void MessageReceived(BMessage* message);
117 private:
118 void _UpdateTextViewColors();
122 // #pragma mark - LabelView
125 LabelView::LabelView(const char* label)
127 BStringView("label", label),
128 fEnabled(true)
130 SetAlignment(B_ALIGN_RIGHT);
134 void
135 LabelView::SetEnabled(bool enabled)
137 if (enabled != fEnabled) {
138 fEnabled = enabled;
139 Invalidate();
144 void
145 LabelView::Draw(BRect updateRect)
147 if (Text() != NULL) {
148 BRect rect = Bounds();
149 // TODO: solve this better (alignment of label and text)
150 rect.top++;
152 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
153 uint32 flags = 0;
154 if (!IsEnabled())
155 flags |= BControlLook::B_DISABLED;
157 be_control_look->DrawLabel(this, Text(), rect, updateRect,
158 base, flags, BAlignment(Alignment(), B_ALIGN_MIDDLE));
163 // #pragma mark - HeaderTextControl
166 HeaderTextControl::HeaderTextControl(const char* label, const char* name,
167 BMessage* message)
169 BTextControl(label, name, message)
174 void
175 HeaderTextControl::AttachedToWindow()
177 BTextControl::AttachedToWindow();
178 _UpdateTextViewColors();
182 void
183 HeaderTextControl::SetEnabled(bool enabled)
185 BTextControl::SetEnabled(enabled);
186 _UpdateTextViewColors();
190 void
191 HeaderTextControl::Draw(BRect updateRect)
193 bool enabled = IsEnabled();
194 bool active = TextView()->IsFocus() && Window()->IsActive();
196 BRect rect = TextView()->Frame();
197 rect.InsetBy(-2, -2);
199 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
200 uint32 flags = 0;
201 if (!enabled)
202 flags = BControlLook::B_DISABLED;
204 if (enabled) {
205 if (active)
206 flags |= BControlLook::B_FOCUSED;
208 be_control_look->DrawTextControlBorder(this, rect, updateRect, base,
209 flags);
212 if (Label() != NULL) {
213 rect = CreateLabelLayoutItem()->Frame().OffsetByCopy(-Frame().left,
214 -Frame().top);
215 // TODO: solve this better (alignment of label and text)
216 rect.top++;
218 alignment labelAlignment;
219 GetAlignment(&labelAlignment, NULL);
221 be_control_look->DrawLabel(this, Label(), rect, updateRect,
222 base, flags, BAlignment(labelAlignment, B_ALIGN_MIDDLE));
227 void
228 HeaderTextControl::MessageReceived(BMessage* message)
230 switch (message->what) {
231 case M_SELECT:
233 BTextView* textView = TextView();
234 if (textView != NULL)
235 textView->SelectAll();
236 break;
239 default:
240 BTextControl::MessageReceived(message);
241 break;
246 void
247 HeaderTextControl::_UpdateTextViewColors()
249 BTextView* textView = TextView();
251 BFont font;
252 textView->GetFontAndColor(0, &font);
254 rgb_color textColor;
255 if (!textView->IsEditable() || IsEnabled())
256 textColor = ui_color(B_DOCUMENT_TEXT_COLOR);
257 else {
258 textColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
259 B_DISABLED_LABEL_TINT);
262 textView->SetFontAndColor(&font, B_FONT_ALL, &textColor);
264 rgb_color color;
265 if (!textView->IsEditable())
266 color = ui_color(B_PANEL_BACKGROUND_COLOR);
267 else if (IsEnabled())
268 color = ui_color(B_DOCUMENT_BACKGROUND_COLOR);
269 else {
270 color = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
271 B_LIGHTEN_2_TINT);
274 textView->SetViewColor(color);
275 textView->SetLowColor(color);
279 // #pragma mark - THeaderView
282 THeaderView::THeaderView(bool incoming, bool resending, int32 defaultAccount)
284 fAccountMenu(NULL),
285 fAccountID(defaultAccount),
286 fFromControl(NULL),
287 fBccControl(NULL),
288 fDateControl(NULL),
289 fIncoming(incoming),
290 fResending(resending)
292 // From
293 if (fIncoming) {
294 fFromControl = new HeaderTextControl(B_TRANSLATE("From:"), NULL, NULL);
295 fFromControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
296 fFromControl->SetEnabled(false);
299 // From accounts menu
300 BMenuField* fromField = NULL;
301 if (!fIncoming || resending) {
302 // And now the "from account" pop-up menu, on the left side, taking the
303 // remaining space.
305 fAccountMenu = new BPopUpMenu(B_EMPTY_STRING);
307 BMailAccounts accounts;
308 bool marked = false;
309 for (int32 i = 0; i < accounts.CountAccounts(); i++) {
310 BMailAccountSettings* account = accounts.AccountAt(i);
311 BString name = account->Name();
312 name << ": " << account->RealName() << " <"
313 << account->ReturnAddress() << ">";
315 BMessage* msg = new BMessage(kMsgFrom);
316 BMenuItem *item = new BMenuItem(name, msg);
318 msg->AddInt32("id", account->AccountID());
320 if (defaultAccount == account->AccountID()) {
321 item->SetMarked(true);
322 marked = true;
324 fAccountMenu->AddItem(item);
327 if (!marked) {
328 BMenuItem *item = fAccountMenu->ItemAt(0);
329 if (item != NULL) {
330 item->SetMarked(true);
331 fAccountID = item->Message()->FindInt32("id");
332 } else {
333 fAccountMenu->AddItem(
334 item = new BMenuItem(B_TRANSLATE("<none>"), NULL));
335 item->SetEnabled(false);
336 fAccountID = ~(int32)0;
338 // default account is invalid, set to marked
339 // TODO: do this differently, no casting and knowledge
340 // of TMailApp here....
341 if (TMailApp* app = dynamic_cast<TMailApp*>(be_app))
342 app->SetDefaultAccount(fAccountID);
345 fromField = new BMenuField("account", B_TRANSLATE("From:"),
346 fAccountMenu, B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
347 fromField->SetAlignment(B_ALIGN_RIGHT);
350 // To
351 fToLabel = new LabelView(B_TRANSLATE("To:"));
352 fToControl = new AddressTextControl(B_TRANSLATE("To:"),
353 new BMessage(TO_FIELD));
354 if (fIncoming || resending) {
355 fToLabel->SetEnabled(false);
356 fToControl->SetEditable(false);
357 fToControl->SetEnabled(false);
360 BMessage* msg = new BMessage(FIELD_CHANGED);
361 msg->AddInt32("bitmask", FIELD_TO);
362 fToControl->SetModificationMessage(msg);
364 // Carbon copy
365 fCcLabel = new LabelView(B_TRANSLATE("Cc:"));
366 fCcControl = new AddressTextControl("cc", new BMessage(CC_FIELD));
367 if (fIncoming) {
368 fCcLabel->SetEnabled(false);
369 fCcControl->SetEditable(false);
370 fCcControl->SetEnabled(false);
371 fCcControl->Hide();
372 fCcLabel->Hide();
374 msg = new BMessage(FIELD_CHANGED);
375 msg->AddInt32("bitmask", FIELD_CC);
376 fCcControl->SetModificationMessage(msg);
378 // Blind carbon copy
379 if (!fIncoming) {
380 fBccControl = new AddressTextControl("bcc", new BMessage(BCC_FIELD));
381 msg = new BMessage(FIELD_CHANGED);
382 msg->AddInt32("bitmask", FIELD_BCC);
383 fBccControl->SetModificationMessage(msg);
386 // Subject
387 fSubjectControl = new HeaderTextControl(B_TRANSLATE("Subject:"), NULL,
388 new BMessage(SUBJECT_FIELD));
389 msg = new BMessage(FIELD_CHANGED);
390 msg->AddInt32("bitmask", FIELD_SUBJECT);
391 fSubjectControl->SetModificationMessage(msg);
392 fSubjectControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
393 if (fIncoming || fResending)
394 fSubjectControl->SetEnabled(false);
396 // Date
397 if (fIncoming) {
398 fDateControl = new HeaderTextControl(B_TRANSLATE("Date:"), NULL, NULL);
399 fDateControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
400 fDateControl->SetEnabled(false);
403 BGridLayout* layout = GridLayout();
405 if (fIncoming)
406 layout->SetHorizontalSpacing(0);
407 layout->SetVerticalSpacing(B_USE_HALF_ITEM_SPACING);
409 int32 row = 0;
410 if (fromField != NULL) {
411 layout->AddItem(fromField->CreateLabelLayoutItem(), 0, row);
412 layout->AddItem(fromField->CreateMenuBarLayoutItem(), 1, row++, 3, 1);
413 } else if (fFromControl != NULL) {
414 layout->AddItem(fFromControl->CreateLabelLayoutItem(), 0, row);
415 layout->AddItem(fFromControl->CreateTextViewLayoutItem(), 1, row++,
416 3, 1);
419 layout->AddView(fToLabel, 0, row);
420 layout->AddView(fToControl, 1, row++, 3, 1);
421 layout->AddView(fCcLabel, 0, row);
422 layout->AddView(fCcControl, 1, row, fIncoming ? 3 : 1, 1);
423 if (fBccControl != NULL) {
424 layout->AddView(new LabelView(B_TRANSLATE("Bcc:")), 2, row);
425 layout->AddView(fBccControl, 3, row++);
426 } else
427 row++;
428 layout->AddItem(fSubjectControl->CreateLabelLayoutItem(), 0, row);
429 layout->AddItem(fSubjectControl->CreateTextViewLayoutItem(), 1, row++,
430 3, 1);
432 if (fDateControl != NULL) {
433 layout->AddItem(fDateControl->CreateLabelLayoutItem(), 0, row);
434 layout->AddItem(fDateControl->CreateTextViewLayoutItem(), 1, row++,
435 3, 1);
440 const char*
441 THeaderView::From() const
443 return fFromControl != NULL ? fFromControl->Text() : NULL;
447 void
448 THeaderView::SetFrom(const char* from)
450 if (fFromControl != NULL)
451 fFromControl->SetText(from);
455 bool
456 THeaderView::IsToEmpty() const
458 return To() == NULL || To()[0] == '\0';
462 const char*
463 THeaderView::To() const
465 return fToControl->Text();
469 void
470 THeaderView::SetTo(const char* to)
472 fToControl->SetText(to);
476 bool
477 THeaderView::IsCcEmpty() const
479 return Cc() == NULL || Cc()[0] == '\0';
483 const char*
484 THeaderView::Cc() const
486 return fCcControl != NULL ? fCcControl->Text() : NULL;
490 void
491 THeaderView::SetCc(const char* cc)
493 fCcControl->SetText(cc);
495 if (fIncoming) {
496 if (cc != NULL && cc[0] != '\0') {
497 if (fCcControl->IsHidden(this)) {
498 fCcControl->Show();
499 fCcLabel->Show();
501 } else if (!fCcControl->IsHidden(this)) {
502 fCcControl->Hide();
503 fCcLabel->Hide();
509 bool
510 THeaderView::IsBccEmpty() const
512 return Bcc() == NULL || Bcc()[0] == '\0';
516 const char*
517 THeaderView::Bcc() const
519 return fBccControl != NULL ? fBccControl->Text() : NULL;
523 void
524 THeaderView::SetBcc(const char* bcc)
526 if (fBccControl != NULL)
527 fBccControl->SetText(bcc);
531 bool
532 THeaderView::IsSubjectEmpty() const
534 return Subject() == NULL || Subject()[0] == '\0';
538 const char*
539 THeaderView::Subject() const
541 return fSubjectControl->Text();
545 void
546 THeaderView::SetSubject(const char* subject)
548 fSubjectControl->SetText(subject);
552 bool
553 THeaderView::IsDateEmpty() const
555 return Date() == NULL || Date()[0] == '\0';
559 const char*
560 THeaderView::Date() const
562 return fDateControl != NULL ? fDateControl->Text() : NULL;
566 void
567 THeaderView::SetDate(time_t date)
569 fDate = date;
571 if (fDateControl != NULL) {
572 BDateTimeFormat formatter;
574 BString string;
575 formatter.Format(string, date, B_FULL_DATE_FORMAT,
576 B_MEDIUM_TIME_FORMAT);
577 SetDate(string);
582 void
583 THeaderView::SetDate(const char* date)
585 if (fDateControl != NULL)
586 fDateControl->SetText(date);
590 int32
591 THeaderView::AccountID() const
593 return fAccountID;
597 const char*
598 THeaderView::AccountName() const
600 BMenuItem* menuItem = fAccountMenu->FindMarked();
601 if (menuItem != NULL)
602 return menuItem->Label();
604 return NULL;
608 void
609 THeaderView::SetAccount(int32 id)
611 fAccountID = id;
613 if (fAccountMenu == NULL)
614 return;
616 for (int32 i = fAccountMenu->CountItems(); i-- > 0;) {
617 BMenuItem* item = fAccountMenu->ItemAt(i);
618 if (item == NULL)
619 continue;
621 BMessage* message = item->Message();
622 if (message->GetInt32("id", -1) == id) {
623 item->SetMarked(true);
624 break;
630 void
631 THeaderView::SetAccount(const char* name)
633 if (fAccountMenu == NULL)
634 return;
636 BMenuItem* item = fAccountMenu->FindItem(name);
637 if (item != NULL) {
638 item->SetMarked(true);
639 fAccountID = item->Message()->GetInt32("id", -1);
644 status_t
645 THeaderView::SetFromMessage(BEmailMessage* mail)
647 // Set Subject:, From:, To: & Cc: fields
648 SetSubject(mail->Subject());
649 SetFrom(mail->From());
650 SetTo(mail->To());
651 SetCc(mail->CC());
653 BString accountName;
654 if (mail->GetAccountName(accountName) == B_OK)
655 SetAccount(accountName);
657 // Set the date on this message
658 time_t date = mail->Date();
659 if (date <= 0) {
660 const char* dateField = mail->HeaderField("Date");
661 SetDate(dateField != NULL ? dateField : B_TRANSLATE("Unknown"));
662 } else
663 SetDate(date);
665 return B_OK;
669 void
670 THeaderView::MessageReceived(BMessage *msg)
672 switch (msg->what) {
673 case B_SIMPLE_DATA:
675 BTextView* textView = dynamic_cast<BTextView*>(Window()->CurrentFocus());
676 if (dynamic_cast<AddressTextControl *>(textView->Parent()) != NULL)
677 textView->Parent()->MessageReceived(msg);
678 else {
679 BMessage message(*msg);
680 message.what = REFS_RECEIVED;
681 Window()->PostMessage(&message, Window());
683 break;
686 case kMsgFrom:
688 BMenuItem *item;
689 if (msg->FindPointer("source", (void **)&item) >= B_OK)
690 item->SetMarked(true);
692 int32 account;
693 if (msg->FindInt32("id",(int32 *)&account) >= B_OK)
694 fAccountID = account;
696 BMessage message(FIELD_CHANGED);
697 // field doesn't matter; no special processing for this field
698 // it's just to turn on the save button
699 message.AddInt32("bitmask", 0);
700 Window()->PostMessage(&message, Window());
701 break;
707 void
708 THeaderView::AttachedToWindow()
710 fToControl->SetTarget(Looper());
711 fSubjectControl->SetTarget(Looper());
712 fCcControl->SetTarget(Looper());
713 if (fBccControl != NULL)
714 fBccControl->SetTarget(Looper());
715 if (fAccountMenu != NULL)
716 fAccountMenu->SetTargetForItems(this);
718 BView::AttachedToWindow();