1/* 2 3PDF Writer printer driver. 4 5Copyright (c) 2002 OpenBeOS. 6 7Authors: 8 Philippe Houdoin 9 Simon Gauvin 10 Michael Pfeiffer 11 12Permission is hereby granted, free of charge, to any person obtaining a copy of 13this software and associated documentation files (the "Software"), to deal in 14the Software without restriction, including without limitation the rights to 15use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 16of the Software, and to permit persons to whom the Software is furnished to do 17so, subject to the following conditions: 18 19The above copyright notice and this permission notice shall be included in all 20copies or substantial portions of the Software. 21 22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28THE SOFTWARE. 29 30*/ 31 32#include <InterfaceKit.h> 33#include <SupportKit.h> 34#include "BlockingWindow.h" 35#include "FontsWindow.h" 36#include "Fonts.h" 37 38 39class CJKFontItem : public BStringItem 40{ 41 font_encoding fEncoding; 42 bool fActive; 43 44public: 45 CJKFontItem(const char* label, font_encoding encoding, bool active = true); 46 void SetActive(bool active) { fActive = active; } 47 void DrawItem(BView* owner, BRect rect, bool drawEverything); 48 49 bool Active() const { return fActive; } 50 font_encoding Encoding() const { return fEncoding; } 51}; 52 53CJKFontItem::CJKFontItem(const char* label, font_encoding encoding, bool active) 54 : BStringItem(label) 55 , fEncoding(encoding) 56 , fActive(active) 57{ 58} 59 60void 61CJKFontItem::DrawItem(BView* owner, BRect rect, bool drawEverything) 62{ 63 BStringItem::DrawItem(owner, rect, drawEverything); 64 if (!fActive) { 65 owner->SetHighColor(0, 0, 0, 0); 66 float y = (rect.top + rect.bottom) / 2; 67 owner->StrokeLine(BPoint(rect.left, y), BPoint(rect.right, y)); 68 } 69} 70 71static const char* FontName(font_encoding enc) { 72 switch(enc) { 73 case japanese_encoding: return "Japanese"; 74 case chinese_cns1_encoding: return "Traditional Chinese"; 75 case chinese_gb1_encoding: return "Simplified Chinese"; 76 case korean_encoding: return "Korean"; 77 default: return "invalid font encoding!"; 78 } 79} 80 81 82// #pragma mark -- of DragListView 83 84 85DragListView::DragListView(BRect frame, const char *name, 86 list_view_type type, 87 uint32 resizingMode, uint32 flags) 88 : BListView(frame, name, type, resizingMode, flags) 89{ 90} 91 92 93bool 94DragListView::InitiateDrag(BPoint point, int32 index, bool wasSelected) 95{ 96 BMessage m; 97 DragMessage(&m, ItemFrame(index), this); 98 return true; 99} 100 101 102/** 103 * Constuctor 104 * 105 * @param 106 * @return 107 */ 108FontsWindow::FontsWindow(Fonts *fonts) 109 : HWindow(BRect(0,0,400,220), "Fonts", B_TITLED_WINDOW_LOOK, 110 B_MODAL_APP_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | 111 B_NOT_ZOOMABLE | B_CLOSE_ON_ESCAPE) 112{ 113 // ---- Ok, build a default page setup user interface 114 BRect r, r1; 115 BView *panel; 116 BButton *button; 117 float x, y, w, h; 118 BString setting_value; 119 BTabView *tabView; 120 BTab *tab; 121 122 AddShortcut('W',B_COMMAND_KEY,new BMessage(B_QUIT_REQUESTED)); 123 124 fFonts = fonts; 125 126 r = Bounds(); 127 tabView = new BTabView(r, "tab_view"); 128 129 // --- Embedding tab --- 130 tab = new BTab(); 131 132 // add a *dialog* background 133 134 r.bottom -= tabView->TabHeight(); 135 panel = new BView(r, "embedding_panel", B_FOLLOW_ALL, 136 B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP); 137 panel-> SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 138 139 r1 = r; r1.OffsetTo(0, 0); 140 // add font list 141#if USE_CLV 142 fList = new BColumnListView(BRect(r.left+5, r.top+5, r.right-5-B_V_SCROLL_BAR_WIDTH, r.bottom-5-B_H_SCROLL_BAR_HEIGHT-30), 143 "fonts_list", B_FOLLOW_ALL, B_WILL_DRAW | B_NAVIGABLE_JUMP); 144 panel->AddChild(fList); 145#else 146 fList = new BListView(BRect(r1.left+5, r1.top+5, r1.right-5-B_V_SCROLL_BAR_WIDTH, r1.bottom-5-B_H_SCROLL_BAR_HEIGHT-30), 147 "fonts_list", B_MULTIPLE_SELECTION_LIST); 148 panel->AddChild(new BScrollView("scroll_list", fList, 149 B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true)); 150 fList->SetSelectionMessage(new BMessage(SELECTION_MSG)); 151#endif 152 FillFontList(); 153 154 // add a "Embed" button, and make it default 155 button = new BButton(r1, NULL, "Embed", new BMessage(EMBED_MSG), 156 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 157 button->ResizeToPreferred(); 158 button->GetPreferredSize(&w, &h); 159 x = r1.right - w - 8; 160 y = r1.bottom - h - 8; 161 button->MoveTo(x, y); 162 button->SetEnabled(false); 163 panel->AddChild(button); 164 button->MakeDefault(true); 165 fEmbedButton = button; 166 167 // add a "Substitute" button 168 button = new BButton(r, NULL, "Substitute", new BMessage(SUBST_MSG), 169 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 170 button->GetPreferredSize(&w, &h); 171 button->ResizeToPreferred(); 172 button->MoveTo(x - w - 8, y); 173 button->SetEnabled(false); 174 panel->AddChild(button); 175 fSubstButton = button; 176 177 // add a separator line... 178 BBox * line = new BBox(BRect(r1.left, y - 9, r1.right, y - 8), NULL, 179 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM ); 180 panel->AddChild(line); 181 182 tabView->AddTab(panel, tab); 183 tab->SetLabel("Embedding"); 184 185 // --- CJK tab --- 186 tab = new BTab(); 187 188 // add a *dialog* background 189 panel = new BView(r, "cjk_panel", B_FOLLOW_ALL, 190 B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP); 191 panel-> SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 192 193 BListView* list = 194 new DragListView(BRect(r1.left+5, r1.top+5, r1.right-5-B_V_SCROLL_BAR_WIDTH, r1.bottom-5-B_H_SCROLL_BAR_HEIGHT-30), 195 "cjk", B_MULTIPLE_SELECTION_LIST); 196 panel->AddChild(new BScrollView("cjk_scroll_list", list, 197 B_FOLLOW_LEFT | B_FOLLOW_TOP, 0, false, true)); 198 199 font_encoding enc; bool active; 200 for (int i = 0; fFonts->GetCJKOrder(i, enc, active); i++) { 201 list->AddItem(new CJKFontItem(FontName(enc), enc, active)); 202 } 203 list->SetSelectionMessage(new BMessage(CJK_SELECTION_MSG)); 204 fCJKList = list; 205 206 // add a "Embed" button 207 button = new BButton(r, NULL, "Enable", new BMessage(ENABLE_MSG), 208 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 209 button->ResizeToPreferred(); 210 button->GetPreferredSize(&w, &h); 211 x = r1.right - w - 8; 212 y = r1.bottom - h - 8; 213 button->MoveTo(x, y); 214 button->SetEnabled(false); 215 panel->AddChild(button); 216 fEnableButton = button; 217 218 // add a "Disable" button 219 button = new BButton(r, NULL, "Disable", new BMessage(DISABLE_MSG), 220 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 221 button->GetPreferredSize(&w, &h); 222 button->ResizeToPreferred(); 223 x -= w + 8; 224 button->MoveTo(x, y); 225 button->SetEnabled(false); 226 panel->AddChild(button); 227 fDisableButton = button; 228 229 // add a "Down" button 230 button = new BButton(r, NULL, "Down", new BMessage(DOWN_MSG), 231 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 232 button->GetPreferredSize(&w, &h); 233 button->ResizeToPreferred(); 234 x -= w + 8; 235 button->MoveTo(x, y); 236 button->SetEnabled(false); 237 panel->AddChild(button); 238 fDownButton = button; 239 240 // add a "Up" button 241 button = new BButton(r, NULL, "Up", new BMessage(UP_MSG), 242 B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); 243 button->GetPreferredSize(&w, &h); 244 button->ResizeToPreferred(); 245 x -= w + 8; 246 button->MoveTo(x, y); 247 button->SetEnabled(false); 248 panel->AddChild(button); 249 fUpButton = button; 250 251 // add a separator line... 252 line = new BBox(BRect(r1.left, y - 9, r1.right, y - 8), NULL, 253 B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM ); 254 panel->AddChild(line); 255 256 257 tabView->AddTab(panel, tab); 258 tab->SetLabel("CJK"); 259 260 // add the tabView to the window 261 AddChild(tabView); 262 263 MoveTo(320, 320); 264} 265 266 267// -------------------------------------------------- 268FontsWindow::~FontsWindow() 269{ 270} 271 272 273// -------------------------------------------------- 274bool 275FontsWindow::QuitRequested() 276{ 277 return true; 278} 279 280 281// -------------------------------------------------- 282void 283FontsWindow::Quit() 284{ 285 inherited::Quit(); 286} 287 288 289class ListIterator 290{ 291 virtual bool DoItem(BListItem* item) = 0; 292public: 293 static bool DoIt(BListItem* item, void* data); 294 virtual ~ListIterator() {} 295}; 296 297 298bool 299ListIterator::DoIt(BListItem* item, void* data) 300{ 301 if (item->IsSelected()) { 302 ListIterator* e = (ListIterator*)data; 303 return e->DoItem(item); 304 } 305 return false; 306} 307 308class CountItems : public ListIterator 309{ 310 BListView* fList; 311 Fonts* fFonts; 312 int fNumEmbed; 313 int fNumSubst; 314 315 bool DoItem(BListItem* item); 316 317public: 318 CountItems(BListView* list, Fonts* fonts); 319 int GetNumEmbed() { return fNumEmbed; } 320 int GetNumSubst() { return fNumSubst; } 321}; 322 323CountItems::CountItems(BListView* list, Fonts* fonts) 324 : fList(list) 325 , fFonts(fonts) 326 , fNumEmbed(0) 327 , fNumSubst(0) 328{ } 329 330bool CountItems::DoItem(BListItem* item) 331{ 332 int32 i = fList->IndexOf(item); 333 if (0 <= i && i < fFonts->Length()) { 334 if (fFonts->At(i)->Embed()) { 335 fNumEmbed ++; 336 } else { 337 fNumSubst ++; 338 } 339 } 340 return false; 341} 342 343class EmbedFont : public ListIterator 344{ 345 FontsWindow* fWindow; 346 BListView* fList; 347 Fonts* fFonts; 348 bool fEmbed; 349 350 bool DoItem(BListItem* item); 351public: 352 EmbedFont(FontsWindow* window, BListView* list, Fonts* fonts, bool embed); 353}; 354 355EmbedFont::EmbedFont(FontsWindow* window, BListView* list, Fonts* fonts, bool embed) 356 : fWindow(window) 357 , fList(list) 358 , fFonts(fonts) 359 , fEmbed(embed) 360{ 361} 362 363bool 364EmbedFont::DoItem(BListItem* item) 365{ 366 int32 i = fList->IndexOf(item); 367 if (0 <= i && i < fFonts->Length()) { 368 fFonts->At(i)->SetEmbed(fEmbed); 369 fWindow->SetItemText((BStringItem*)item, fFonts->At(i)); 370 } 371 return false; 372} 373 374// move selected item in list one position up or down 375void 376FontsWindow::MoveItemInList(BListView* list, bool up) 377{ 378 int32 from = list->CurrentSelection(0); 379 if (from >= 0) { 380 int32 to; 381 if (up) { 382 if (from == 0) return; // at top of list 383 to = from - 1; 384 } else { 385 if (from == list->CountItems() -1) return; // at bottom of list 386 to = from + 1; 387 } 388 list->SwapItems(from, to); 389 390 font_encoding enc; 391 bool active; 392 fFonts->GetCJKOrder(from, enc, active); 393 394 font_encoding enc1; 395 bool active1; 396 fFonts->GetCJKOrder(to, enc1, active1); 397 fFonts->SetCJKOrder(to, enc, active); 398 fFonts->SetCJKOrder(from, enc1, active1); 399 } 400} 401 402 403void 404FontsWindow::EnableItemInList(BListView* list, bool enable) 405{ 406 int32 i = list->CurrentSelection(0); 407 if (i >= 0) { 408 BListItem* item0 = list->ItemAt(i); 409 CJKFontItem* item = dynamic_cast<CJKFontItem*>(item0); 410 if (item) { 411 item->SetActive(enable); 412 list->Invalidate(); 413 font_encoding enc; 414 bool active; 415 fFonts->GetCJKOrder(i, enc, active); 416 fFonts->SetCJKOrder(i, enc, enable); 417 } 418 } 419} 420 421// -------------------------------------------------- 422void 423FontsWindow::MessageReceived(BMessage *msg) 424{ 425 switch (msg->what){ 426 case OK_MSG: Quit(); 427 break; 428 429 case CANCEL_MSG: Quit(); 430 break; 431 432 case EMBED_MSG: 433 { 434 #if USE_CLV 435 #else 436 EmbedFont e(this, fList, fFonts, true); 437 fList->DoForEach(EmbedFont::DoIt, (void*)&e); 438 } 439 PostMessage(SELECTION_MSG); 440 fList->Invalidate(); 441 #endif 442 break; 443 444 case SUBST_MSG: 445 { 446 #if USE_CLV 447 #else 448 EmbedFont e(this, fList, fFonts, false); 449 fList->DoForEach(EmbedFont::DoIt, (void*)&e); 450 } 451 PostMessage(SELECTION_MSG); 452 fList->Invalidate(); 453 #endif 454 break; 455 456 case SELECTION_MSG: 457 { 458 CountItems count(fList, fFonts); 459 fList->DoForEach(CountItems::DoIt, (void*)&count); 460 fEmbedButton->SetEnabled(count.GetNumSubst() > 0); 461 fSubstButton->SetEnabled(count.GetNumEmbed() > 0); 462 } 463 break; 464 465 case UP_MSG: 466 case DOWN_MSG: 467 MoveItemInList(fCJKList, msg->what == UP_MSG); 468 PostMessage(CJK_SELECTION_MSG); 469 break; 470 471 case ENABLE_MSG: 472 case DISABLE_MSG: 473 EnableItemInList(fCJKList, msg->what == ENABLE_MSG); 474 PostMessage(CJK_SELECTION_MSG); 475 break; 476 477 case CJK_SELECTION_MSG: 478 { 479 int32 i = fCJKList->CurrentSelection(0); 480 if (i >= 0) { 481 BListItem* item0 = fCJKList->ItemAt(i); 482 CJKFontItem* item = dynamic_cast<CJKFontItem*>(item0); 483 if (item) { 484 fUpButton->SetEnabled(i != 0); 485 fDownButton->SetEnabled(i != fCJKList->CountItems()-1); 486 fEnableButton->SetEnabled(!item->Active()); 487 fDisableButton->SetEnabled(item->Active()); 488 } 489 } 490 } 491 break; 492 493 default: 494 inherited::MessageReceived(msg); 495 break; 496 } 497} 498 499void 500FontsWindow::SetItemText(BStringItem* i, FontFile* f) 501{ 502 const int64 KB = 1024; 503 const int64 MB = KB * KB; 504 char buffer[40]; 505 BString s; 506 s << f->Name() << ": "; 507 if (f->Type() == true_type_type) s << "TrueType"; 508 else s << "Type 1"; 509 s << " ("; 510 if (f->Size() >= MB) { 511 sprintf(buffer, "%d MB", (int)(f->Size()/MB)); 512 } else if (f->Size() >= KB) { 513 sprintf(buffer, "%d KB", (int)(f->Size()/KB)); 514 } else { 515 sprintf(buffer, "%d B", (int)(f->Size())); 516 } 517 s << buffer; 518 s << ") "; 519 s << (f->Embed() ? "embed" : "substitute"); 520 i->SetText(s.String()); 521} 522 523void 524FontsWindow::FillFontList() 525{ 526 const int n = fFonts->Length(); 527 for (int i = 0; i < n; i++) { 528#if USE_CLV 529#else 530 BStringItem* s; 531 FontFile* f = fFonts->At(i); 532 fList->AddItem(s = new BStringItem("")); 533 SetItemText(s, f); 534#endif 535 } 536} 537 538void 539FontsWindow::EmptyFontList() 540{ 541#if USE_CLV 542#else 543 const int n = fList->CountItems(); 544 for (int i = 0; i < n; i++) { 545 BListItem* item = fList->ItemAt(i); 546 delete item; 547 } 548 fList->MakeEmpty(); 549#endif 550} 551