1 /*
2 * Copyright 2009-2013 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * DarkWyrm, bpmagic@columbus.rr.com
7 * Adrien Destugues, pulkomandy@gmail.com
8 * John Scipione, jscipione@gmail.com
9 */
10
11
12 /*! Decorator resembling Mac OS 8 and 9 */
13
14
15 #include "MacDecorator.h"
16
17 #include <new>
18 #include <stdio.h>
19
20 #include <GradientLinear.h>
21 #include <Point.h>
22 #include <View.h>
23
24 #include "DesktopSettings.h"
25 #include "DrawingEngine.h"
26 #include "PatternHandler.h"
27 #include "RGBColor.h"
28
29
30 //#define DEBUG_DECORATOR
31 #ifdef DEBUG_DECORATOR
32 # define STRACE(x) printf x
33 #else
34 # define STRACE(x) ;
35 #endif
36
37
MacDecorAddOn(image_id id,const char * name)38 MacDecorAddOn::MacDecorAddOn(image_id id, const char* name)
39 :
40 DecorAddOn(id, name)
41 {
42 }
43
44
45 Decorator*
_AllocateDecorator(DesktopSettings & settings,BRect rect,Desktop * desktop)46 MacDecorAddOn::_AllocateDecorator(DesktopSettings& settings, BRect rect,
47 Desktop* desktop)
48 {
49 return new (std::nothrow)MacDecorator(settings, rect, desktop);
50 }
51
52
MacDecorator(DesktopSettings & settings,BRect frame,Desktop * desktop)53 MacDecorator::MacDecorator(DesktopSettings& settings, BRect frame,
54 Desktop* desktop)
55 :
56 SATDecorator(settings, frame, desktop),
57 fButtonHighColor((rgb_color) { 232, 232, 232, 255 }),
58 fButtonLowColor((rgb_color) { 128, 128, 128, 255 }),
59 fFrameHighColor((rgb_color) { 255, 255, 255, 255 }),
60 fFrameMidColor((rgb_color) { 216, 216, 216, 255 }),
61 fFrameLowColor((rgb_color) { 156, 156, 156, 255 }),
62 fFrameLowerColor((rgb_color) { 0, 0, 0, 255 }),
63 fFocusTextColor(settings.UIColor(B_WINDOW_TEXT_COLOR)),
64 fNonFocusTextColor(settings.UIColor(B_WINDOW_INACTIVE_TEXT_COLOR))
65 {
66 STRACE(("MacDecorator()\n"));
67 STRACE(("\tFrame (%.1f,%.1f,%.1f,%.1f)\n",
68 frame.left, frame.top, frame.right, frame.bottom));
69 }
70
71
~MacDecorator()72 MacDecorator::~MacDecorator()
73 {
74 STRACE(("~MacDecorator()\n"));
75 }
76
77
78 // TODO : Add GetSettings
79
80
81 void
Draw(BRect updateRect)82 MacDecorator::Draw(BRect updateRect)
83 {
84 STRACE(("MacDecorator: Draw(BRect updateRect): "));
85 updateRect.PrintToStream();
86
87 // We need to draw a few things: the tab, the borders,
88 // and the buttons
89 fDrawingEngine->SetDrawState(&fDrawState);
90
91 _DrawFrame(updateRect & fBorderRect);
92 _DrawTabs(updateRect & fTitleBarRect);
93 }
94
95
96 void
Draw()97 MacDecorator::Draw()
98 {
99 STRACE("MacDecorator::Draw()\n");
100 fDrawingEngine->SetDrawState(&fDrawState);
101
102 _DrawFrame(fBorderRect);
103 _DrawTabs(fTitleBarRect);
104 }
105
106
107 // TODO : add GetSizeLimits
108
109
110 Decorator::Region
RegionAt(BPoint where,int32 & tab) const111 MacDecorator::RegionAt(BPoint where, int32& tab) const
112 {
113 // Let the base class version identify hits of the buttons and the tab.
114 Region region = Decorator::RegionAt(where, tab);
115 if (region != REGION_NONE)
116 return region;
117
118 // check the resize corner
119 if (fTopTab->look == B_DOCUMENT_WINDOW_LOOK && fResizeRect.Contains(where))
120 return REGION_RIGHT_BOTTOM_CORNER;
121
122 // hit-test the borders
123 if (!(fTopTab->flags & B_NOT_RESIZABLE)
124 && (fTopTab->look == B_TITLED_WINDOW_LOOK
125 || fTopTab->look == B_FLOATING_WINDOW_LOOK
126 || fTopTab->look == B_MODAL_WINDOW_LOOK)
127 && fBorderRect.Contains(where) && !fFrame.Contains(where)) {
128 return REGION_BOTTOM_BORDER;
129 // TODO: Determine the actual border!
130 }
131
132 return REGION_NONE;
133 }
134
135
136 bool
SetRegionHighlight(Region region,uint8 highlight,BRegion * dirty,int32 tabIndex)137 MacDecorator::SetRegionHighlight(Region region, uint8 highlight,
138 BRegion* dirty, int32 tabIndex)
139 {
140 Decorator::Tab* tab
141 = static_cast<Decorator::Tab*>(_TabAt(tabIndex));
142 if (tab != NULL) {
143 tab->isHighlighted = highlight != 0;
144 // Invalidate the bitmap caches for the close/minimize/zoom button
145 // when the highlight changes.
146 switch (region) {
147 case REGION_CLOSE_BUTTON:
148 if (highlight != RegionHighlight(region))
149 memset(&tab->closeBitmaps, 0, sizeof(tab->closeBitmaps));
150 break;
151
152 case REGION_MINIMIZE_BUTTON:
153 if (highlight != RegionHighlight(region)) {
154 memset(&tab->minimizeBitmaps, 0,
155 sizeof(tab->minimizeBitmaps));
156 }
157 break;
158
159 case REGION_ZOOM_BUTTON:
160 if (highlight != RegionHighlight(region))
161 memset(&tab->zoomBitmaps, 0, sizeof(tab->zoomBitmaps));
162 break;
163
164 default:
165 break;
166 }
167 }
168
169 return Decorator::SetRegionHighlight(region, highlight, dirty, tabIndex);
170 }
171
172
173 void
_DoLayout()174 MacDecorator::_DoLayout()
175 {
176 STRACE(("MacDecorator: Do Layout\n"));
177
178 // Here we determine the size of every rectangle that we use
179 // internally when we are given the size of the client rectangle.
180
181 const int32 kDefaultBorderWidth = 6;
182
183 bool hasTab = false;
184
185 if (fTopTab) {
186 switch (fTopTab->look) {
187 case B_MODAL_WINDOW_LOOK:
188 fBorderWidth = kDefaultBorderWidth;
189 break;
190
191 case B_TITLED_WINDOW_LOOK:
192 case B_DOCUMENT_WINDOW_LOOK:
193 hasTab = true;
194 fBorderWidth = kDefaultBorderWidth;
195 break;
196
197 case B_FLOATING_WINDOW_LOOK:
198 hasTab = true;
199 fBorderWidth = 3;
200 break;
201
202 case B_BORDERED_WINDOW_LOOK:
203 fBorderWidth = 1;
204 break;
205
206 default:
207 fBorderWidth = 0;
208 }
209 } else
210 fBorderWidth = 0;
211
212 fBorderRect = fFrame.InsetByCopy(-fBorderWidth, -fBorderWidth);
213
214 // calculate our tab rect
215 if (hasTab) {
216 fBorderRect.top += 3;
217
218 font_height fontHeight;
219 fDrawState.Font().GetHeight(fontHeight);
220
221 // TODO the tab is drawn in a fixed height for now
222 fTitleBarRect.Set(fFrame.left - fBorderWidth,
223 fFrame.top - 22,
224 ((fFrame.right - fFrame.left) < 32.0 ?
225 fFrame.left + 32.0 : fFrame.right) + fBorderWidth,
226 fFrame.top - 3);
227
228 for (int32 i = 0; i < fTabList.CountItems(); i++) {
229 Decorator::Tab* tab = fTabList.ItemAt(i);
230
231 tab->tabRect = fTitleBarRect;
232 // TODO actually handle multiple tabs
233
234 tab->zoomRect = fTitleBarRect;
235 tab->zoomRect.left = tab->zoomRect.right - 12;
236 tab->zoomRect.bottom = tab->zoomRect.top + 12;
237 tab->zoomRect.OffsetBy(-4, 4);
238
239 tab->closeRect = tab->zoomRect;
240 tab->minimizeRect = tab->zoomRect;
241
242 tab->closeRect.OffsetTo(fTitleBarRect.left + 4,
243 fTitleBarRect.top + 4);
244
245 tab->zoomRect.OffsetBy(0 - (tab->zoomRect.Width() + 4), 0);
246 if (Title(tab) != NULL && fDrawingEngine != NULL) {
247 tab->truncatedTitle = Title(tab);
248 fDrawingEngine->SetFont(fDrawState.Font());
249 tab->truncatedTitleLength
250 = (int32)fDrawingEngine->StringWidth(Title(tab),
251 strlen(Title(tab)));
252
253 if (tab->truncatedTitleLength < (tab->zoomRect.left
254 - tab->closeRect.right - 10)) {
255 // start with offset from closerect.right
256 tab->textOffset = int(((tab->zoomRect.left - 5)
257 - (tab->closeRect.right + 5)) / 2);
258 tab->textOffset -= int(tab->truncatedTitleLength / 2);
259
260 // now make it the offset from fTabRect.left
261 tab->textOffset += int(tab->closeRect.right + 5
262 - fTitleBarRect.left);
263 } else
264 tab->textOffset = int(tab->closeRect.right) + 5;
265 } else
266 tab->textOffset = 0;
267 }
268 } else {
269 for (int32 i = 0; i < fTabList.CountItems(); i++) {
270 Decorator::Tab* tab = fTabList.ItemAt(i);
271
272 tab->tabRect.Set(0.0, 0.0, -1.0, -1.0);
273 tab->closeRect.Set(0.0, 0.0, -1.0, -1.0);
274 tab->zoomRect.Set(0.0, 0.0, -1.0, -1.0);
275 tab->minimizeRect.Set(0.0, 0.0, -1.0, -1.0);
276 }
277 }
278 }
279
280
281 void
_DrawFrame(BRect invalid)282 MacDecorator::_DrawFrame(BRect invalid)
283 {
284 if (fTopTab->look == B_NO_BORDER_WINDOW_LOOK)
285 return;
286
287 if (fBorderWidth <= 0)
288 return;
289
290 BRect r = fBorderRect;
291 switch (fTopTab->look) {
292 case B_TITLED_WINDOW_LOOK:
293 case B_DOCUMENT_WINDOW_LOOK:
294 case B_MODAL_WINDOW_LOOK:
295 {
296 if (IsFocus(fTopTab)) {
297 BPoint offset = r.LeftTop();
298 BPoint pt2 = r.LeftBottom();
299
300 // Draw the left side of the frame
301 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowerColor);
302 offset.x++;
303 pt2.x++;
304 pt2.y--;
305
306 fDrawingEngine->StrokeLine(offset, pt2, fFrameHighColor);
307 offset.x++;
308 pt2.x++;
309 pt2.y--;
310
311 fDrawingEngine->StrokeLine(offset, pt2, fFrameMidColor);
312 offset.x++;
313 pt2.x++;
314 fDrawingEngine->StrokeLine(offset, pt2, fFrameMidColor);
315 offset.x++;
316 pt2.x++;
317 pt2.y--;
318
319 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowColor);
320 offset.x++;
321 offset.y += 2;
322 BPoint topleftpt = offset;
323 pt2.x++;
324 pt2.y--;
325
326 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowerColor);
327
328 offset = r.RightTop();
329 pt2 = r.RightBottom();
330
331 // Draw the right side of the frame
332 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowerColor);
333 offset.x--;
334 pt2.x--;
335
336 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowColor);
337 offset.x--;
338 pt2.x--;
339
340 fDrawingEngine->StrokeLine(offset, pt2, fFrameMidColor);
341 offset.x--;
342 pt2.x--;
343 fDrawingEngine->StrokeLine(offset, pt2, fFrameMidColor);
344 offset.x--;
345 pt2.x--;
346
347 fDrawingEngine->StrokeLine(offset, pt2, fFrameHighColor);
348 offset.x--;
349 offset.y += 2;
350 BPoint toprightpt = offset;
351 pt2.x--;
352
353 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowerColor);
354
355 // Draw the top side of the frame that is not in the tab
356 if (fTopTab->look == B_MODAL_WINDOW_LOOK) {
357 offset = r.LeftTop();
358 pt2 = r.RightTop();
359
360 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowerColor);
361 offset.x++;
362 offset.y++;
363 pt2.x--;
364 pt2.y++;
365
366 fDrawingEngine->StrokeLine(offset, pt2, fFrameHighColor);
367 offset.x++;
368 offset.y++;
369 pt2.x--;
370 pt2.y++;
371
372 fDrawingEngine->StrokeLine(offset, pt2, fFrameMidColor);
373 offset.x++;
374 offset.y++;
375 pt2.x--;
376 pt2.y++;
377
378 fDrawingEngine->StrokeLine(offset, pt2, fFrameMidColor);
379 offset.x++;
380 offset.y++;
381 pt2.x--;
382 pt2.y++;
383
384 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowColor);
385 offset.x++;
386 offset.y++;
387 pt2.x--;
388 pt2.y++;
389
390 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowerColor);
391 } else {
392 // Some odd stuff here where the title bar is melded into the
393 // window border so that the sides are drawn into the title
394 // so we draw this bottom up
395 offset = topleftpt;
396 pt2 = toprightpt;
397
398 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowerColor);
399 offset.y--;
400 offset.x++;
401 pt2.y--;
402
403 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowColor);
404 }
405
406 // Draw the bottom side of the frame
407 offset = r.LeftBottom();
408 pt2 = r.RightBottom();
409
410 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowerColor);
411 offset.x++;
412 offset.y--;
413 pt2.x--;
414 pt2.y--;
415
416 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowColor);
417 offset.x++;
418 offset.y--;
419 pt2.x--;
420 pt2.y--;
421
422 fDrawingEngine->StrokeLine(offset, pt2, fFrameMidColor);
423 offset.x++;
424 offset.y--;
425 pt2.x--;
426 pt2.y--;
427
428 fDrawingEngine->StrokeLine(offset, pt2, fFrameMidColor);
429 offset.x++;
430 offset.y--;
431 pt2.x--;
432 pt2.y--;
433
434 fDrawingEngine->StrokeLine(offset, pt2, fFrameHighColor);
435 offset.x += 2;
436 offset.y--;
437 pt2.x--;
438 pt2.y--;
439
440 fDrawingEngine->StrokeLine(offset, pt2, fFrameLowerColor);
441 offset.y--;
442 pt2.x--;
443 pt2.y--;
444 } else {
445 r.top -= 3;
446 RGBColor inactive(82, 82, 82);
447
448 fDrawingEngine->StrokeLine(r.LeftTop(), r.LeftBottom(),
449 inactive);
450 fDrawingEngine->StrokeLine(r.RightTop(), r.RightBottom(),
451 inactive);
452 fDrawingEngine->StrokeLine(r.LeftBottom(), r.RightBottom(),
453 inactive);
454
455 for (int i = 0; i < 4; i++) {
456 r.InsetBy(1, 1);
457 fDrawingEngine->StrokeLine(r.LeftTop(), r.LeftBottom(),
458 fFrameMidColor);
459 fDrawingEngine->StrokeLine(r.RightTop(), r.RightBottom(),
460 fFrameMidColor);
461 fDrawingEngine->StrokeLine(r.LeftBottom(), r.RightBottom(),
462 fFrameMidColor);
463 fDrawingEngine->StrokeLine(r.LeftTop(), r.RightTop(),
464 fFrameMidColor);
465 }
466
467 r.InsetBy(1, 1);
468 fDrawingEngine->StrokeLine(r.LeftTop(), r.LeftBottom(),
469 inactive);
470 fDrawingEngine->StrokeLine(r.RightTop(), r.RightBottom(),
471 inactive);
472 fDrawingEngine->StrokeLine(r.LeftBottom(), r.RightBottom(),
473 inactive);
474 fDrawingEngine->StrokeLine(r.LeftTop(), r.RightTop(),
475 inactive);
476 }
477 break;
478 }
479 case B_BORDERED_WINDOW_LOOK:
480 fDrawingEngine->StrokeRect(r, fFrameMidColor);
481 break;
482
483 default:
484 // don't draw a border frame
485 break;
486 }
487 }
488
489
490 void
_DrawTab(Decorator::Tab * tab,BRect invalid)491 MacDecorator::_DrawTab(Decorator::Tab* tab, BRect invalid)
492 {
493 // If a window has a tab, this will draw it and any buttons which are
494 // in it.
495 if (!tab->tabRect.IsValid() || !invalid.Intersects(tab->tabRect))
496 return;
497
498 BRect rect(tab->tabRect);
499 fDrawingEngine->SetHighColor(RGBColor(fFrameMidColor));
500 fDrawingEngine->FillRect(rect, fFrameMidColor);
501
502 if (IsFocus(tab)) {
503 fDrawingEngine->StrokeLine(rect.LeftTop(), rect.RightTop(),
504 fFrameLowerColor);
505 fDrawingEngine->StrokeLine(rect.LeftTop(), rect.LeftBottom(),
506 fFrameLowerColor);
507 fDrawingEngine->StrokeLine(rect.RightBottom(), rect.RightTop(),
508 fFrameLowerColor);
509
510 rect.InsetBy(1, 1);
511 rect.bottom++;
512
513 fDrawingEngine->StrokeLine(rect.LeftTop(), rect.RightTop(),
514 fFrameHighColor);
515 fDrawingEngine->StrokeLine(rect.LeftTop(), rect.LeftBottom(),
516 fFrameHighColor);
517 fDrawingEngine->StrokeLine(rect.RightBottom(), rect.RightTop(),
518 fFrameLowColor);
519
520 // Draw the neat little lines on either side of the title if there's
521 // room
522 float left;
523 if ((tab->flags & B_NOT_CLOSABLE) == 0)
524 left = tab->closeRect.right;
525 else
526 left = tab->tabRect.left;
527
528 float right;
529 if ((tab->flags & B_NOT_ZOOMABLE) == 0)
530 right = tab->zoomRect.left;
531 else if ((tab->flags & B_NOT_MINIMIZABLE) == 0)
532 right = tab->minimizeRect.left;
533 else
534 right = tab->tabRect.right;
535
536 if (tab->tabRect.left + tab->textOffset > left + 5) {
537 RGBColor dark(115, 115, 115);
538
539 // Left side
540
541 BPoint offset(left + 5, tab->closeRect.top);
542 BPoint pt2(tab->tabRect.left + tab->textOffset - 5,
543 tab->closeRect.top);
544
545 fDrawState.SetHighColor(RGBColor(fFrameHighColor));
546 for (int32 i = 0; i < 6; i++) {
547 fDrawingEngine->StrokeLine(offset, pt2,
548 fDrawState.HighColor());
549 offset.y += 2;
550 pt2.y += 2;
551 }
552
553 offset.Set(left + 6, tab->closeRect.top + 1);
554 pt2.Set(tab->tabRect.left + tab->textOffset - 4,
555 tab->closeRect.top + 1);
556
557 fDrawState.SetHighColor(dark);
558 for (int32 i = 0; i < 6; i++) {
559 fDrawingEngine->StrokeLine(offset, pt2,
560 fDrawState.HighColor());
561 offset.y += 2;
562 pt2.y += 2;
563 }
564
565 // Right side
566
567 offset.Set(tab->tabRect.left + tab->textOffset
568 + tab->truncatedTitleLength + 3, tab->zoomRect.top);
569 pt2.Set(right - 8, tab->zoomRect.top);
570
571 if (offset.x < pt2.x) {
572 fDrawState.SetHighColor(RGBColor(fFrameHighColor));
573 for (int32 i = 0; i < 6; i++) {
574 fDrawingEngine->StrokeLine(offset, pt2,
575 fDrawState.HighColor());
576 offset.y += 2;
577 pt2.y += 2;
578 }
579
580 offset.Set(tab->tabRect.left + tab->textOffset
581 + tab->truncatedTitleLength + 4, tab->zoomRect.top + 1);
582 pt2.Set(right - 7, tab->zoomRect.top + 1);
583
584 fDrawState.SetHighColor(dark);
585 for(int32 i = 0; i < 6; i++) {
586 fDrawingEngine->StrokeLine(offset, pt2,
587 fDrawState.HighColor());
588 offset.y += 2;
589 pt2.y += 2;
590 }
591 }
592 }
593
594 _DrawButtons(tab, rect);
595 } else {
596 RGBColor inactive(82, 82, 82);
597 // Not focused - Just draw a plain light grey area with the title
598 // in the middle
599 fDrawingEngine->StrokeLine(rect.LeftTop(), rect.RightTop(),
600 inactive);
601 fDrawingEngine->StrokeLine(rect.LeftTop(), rect.LeftBottom(),
602 inactive);
603 fDrawingEngine->StrokeLine(rect.RightBottom(), rect.RightTop(),
604 inactive);
605 }
606
607 _DrawTitle(tab, tab->tabRect);
608 }
609
610
611 void
_DrawButtons(Decorator::Tab * tab,const BRect & invalid)612 MacDecorator::_DrawButtons(Decorator::Tab* tab, const BRect& invalid)
613 {
614 if ((tab->flags & B_NOT_CLOSABLE) == 0
615 && invalid.Intersects(tab->closeRect)) {
616 _DrawClose(tab, false, tab->closeRect);
617 }
618 if ((tab->flags & B_NOT_MINIMIZABLE) == 0
619 && invalid.Intersects(tab->minimizeRect)) {
620 _DrawMinimize(tab, false, tab->minimizeRect);
621 }
622 if ((tab->flags & B_NOT_ZOOMABLE) == 0
623 && invalid.Intersects(tab->zoomRect)) {
624 _DrawZoom(tab, false, tab->zoomRect);
625 }
626 }
627
628
629 void
_DrawTitle(Decorator::Tab * tab,BRect rect)630 MacDecorator::_DrawTitle(Decorator::Tab* tab, BRect rect)
631 {
632 fDrawingEngine->SetHighColor(IsFocus(tab)
633 ? fFocusTextColor : fNonFocusTextColor);
634
635 fDrawingEngine->SetLowColor(fFrameMidColor);
636
637 tab->truncatedTitle = Title(tab);
638 fDrawState.Font().TruncateString(&tab->truncatedTitle, B_TRUNCATE_END,
639 (tab->zoomRect.left - 5) - (tab->closeRect.right + 5));
640 fDrawingEngine->SetFont(fDrawState.Font());
641
642 fDrawingEngine->DrawString(tab->truncatedTitle, tab->truncatedTitle.Length(),
643 BPoint(fTitleBarRect.left + tab->textOffset,
644 tab->closeRect.bottom - 1));
645 }
646
647
648 void
_DrawClose(Decorator::Tab * tab,bool direct,BRect r)649 MacDecorator::_DrawClose(Decorator::Tab* tab, bool direct, BRect r)
650 {
651 _DrawButton(tab, direct, r, tab->closePressed);
652 }
653
654
655 void
_DrawZoom(Decorator::Tab * tab,bool direct,BRect rect)656 MacDecorator::_DrawZoom(Decorator::Tab* tab, bool direct, BRect rect)
657 {
658 _DrawButton(tab, direct, rect, tab->zoomPressed);
659
660 rect.top++;
661 rect.left++;
662 rect.bottom = rect.top + 6;
663 rect.right = rect.left + 6;
664
665 fDrawState.SetHighColor(RGBColor(33, 33, 33));
666 fDrawingEngine->StrokeRect(rect, fDrawState.HighColor());
667 }
668
669
670 void
_DrawMinimize(Decorator::Tab * tab,bool direct,BRect rect)671 MacDecorator::_DrawMinimize(Decorator::Tab* tab, bool direct, BRect rect)
672 {
673 _DrawButton(tab, direct, rect, tab->minimizePressed);
674
675 rect.InsetBy(1, 5);
676
677 fDrawState.SetHighColor(RGBColor(33, 33, 33));
678 fDrawingEngine->StrokeRect(rect, fDrawState.HighColor());
679 }
680
681
682 void
_SetTitle(Tab * tab,const char * string,BRegion * updateRegion)683 MacDecorator::_SetTitle(Tab* tab, const char* string, BRegion* updateRegion)
684 {
685 // TODO: we could be much smarter about the update region
686 // TODO may this change the other tabs too ? (to make space for a longer
687 // title ?)
688
689 BRect rect = TabRect(tab);
690
691 _DoLayout();
692
693 if (updateRegion == NULL)
694 return;
695
696 rect = rect | TabRect(tab);
697
698 rect.bottom++;
699 // the border will look differently when the title is adjacent
700
701 updateRegion->Include(rect);
702 }
703
704
705 // TODO : _SetFocus
706
707
708 void
_MoveBy(BPoint offset)709 MacDecorator::_MoveBy(BPoint offset)
710 {
711 // Move all internal rectangles the appropriate amount
712 for (int32 i = 0; i < fTabList.CountItems(); i++) {
713 Decorator::Tab* tab = fTabList.ItemAt(i);
714 tab->zoomRect.OffsetBy(offset);
715 tab->minimizeRect.OffsetBy(offset);
716 tab->closeRect.OffsetBy(offset);
717 tab->tabRect.OffsetBy(offset);
718 }
719
720 fFrame.OffsetBy(offset);
721 fTitleBarRect.OffsetBy(offset);
722 fResizeRect.OffsetBy(offset);
723 fBorderRect.OffsetBy(offset);
724 }
725
726
727 void
_ResizeBy(BPoint offset,BRegion * dirty)728 MacDecorator::_ResizeBy(BPoint offset, BRegion* dirty)
729 {
730 // Move all internal rectangles the appropriate amount
731 fFrame.right += offset.x;
732 fFrame.bottom += offset.y;
733
734 fTitleBarRect.right += offset.x;
735 fBorderRect.right += offset.x;
736 fBorderRect.bottom += offset.y;
737 // fZoomRect.OffsetBy(offset.x, 0);
738 // fMinimizeRect.OffsetBy(offset.x, 0);
739 if (dirty) {
740 dirty->Include(fTitleBarRect);
741 dirty->Include(fBorderRect);
742 }
743
744 // TODO probably some other layouting stuff here
745 _DoLayout();
746 }
747
748
749 // TODO : _SetSettings
750
751
752 Decorator::Tab*
_AllocateNewTab()753 MacDecorator::_AllocateNewTab()
754 {
755 Decorator::Tab* tab = new(std::nothrow) Decorator::Tab;
756 if (tab == NULL)
757 return NULL;
758
759 // Set appropriate colors based on the current focus value. In this case,
760 // each decorator defaults to not having the focus.
761 _SetFocus(tab);
762 return tab;
763 }
764
765
766 bool
_AddTab(DesktopSettings & settings,int32 index,BRegion * updateRegion)767 MacDecorator::_AddTab(DesktopSettings& settings, int32 index,
768 BRegion* updateRegion)
769 {
770 _UpdateFont(settings);
771
772 _DoLayout();
773 if (updateRegion != NULL)
774 updateRegion->Include(fTitleBarRect);
775 return true;
776 }
777
778
779 bool
_RemoveTab(int32 index,BRegion * updateRegion)780 MacDecorator::_RemoveTab(int32 index, BRegion* updateRegion)
781 {
782 BRect oldTitle = fTitleBarRect;
783 _DoLayout();
784 if (updateRegion != NULL) {
785 updateRegion->Include(oldTitle);
786 updateRegion->Include(fTitleBarRect);
787 }
788 return true;
789 }
790
791
792 bool
_MoveTab(int32 from,int32 to,bool isMoving,BRegion * updateRegion)793 MacDecorator::_MoveTab(int32 from, int32 to, bool isMoving,
794 BRegion* updateRegion)
795 {
796 return false;
797
798 #if 0
799 MacDecorator::Tab* toTab = _TabAt(to);
800 if (toTab == NULL)
801 return false;
802
803 if (from < to) {
804 fOldMovingTab.OffsetBy(toTab->tabRect.Width(), 0);
805 toTab->tabRect.OffsetBy(-fOldMovingTab.Width(), 0);
806 } else {
807 fOldMovingTab.OffsetBy(-toTab->tabRect.Width(), 0);
808 toTab->tabRect.OffsetBy(fOldMovingTab.Width(), 0);
809 }
810
811 toTab->tabOffset = uint32(toTab->tabRect.left - fLeftBorder.left);
812 _LayoutTabItems(toTab, toTab->tabRect);
813
814 _CalculateTabsRegion();
815
816 if (updateRegion != NULL)
817 updateRegion->Include(fTitleBarRect);
818 return true;
819 #endif
820 }
821
822
823 void
_GetFootprint(BRegion * region)824 MacDecorator::_GetFootprint(BRegion* region)
825 {
826 // This function calculates the decorator's footprint in coordinates
827 // relative to the view. This is most often used to set a Window
828 // object's visible region.
829 if (!region)
830 return;
831
832 region->MakeEmpty();
833
834 if (fTopTab->look == B_NO_BORDER_WINDOW_LOOK)
835 return;
836
837 region->Set(fBorderRect);
838 region->Exclude(fFrame);
839
840 if (fTopTab->look == B_BORDERED_WINDOW_LOOK)
841 return;
842 region->Include(fTitleBarRect);
843 }
844
845
846 void
_UpdateFont(DesktopSettings & settings)847 MacDecorator::_UpdateFont(DesktopSettings& settings)
848 {
849 ServerFont font;
850 if (fTopTab && fTopTab->look == B_FLOATING_WINDOW_LOOK)
851 settings.GetDefaultPlainFont(font);
852 else
853 settings.GetDefaultBoldFont(font);
854
855 font.SetFlags(B_FORCE_ANTIALIASING);
856 font.SetSpacing(B_STRING_SPACING);
857 fDrawState.SetFont(font);
858 }
859
860
861 // #pragma mark - Private methods
862
863
864 // Draw a mac-style button
865 void
_DrawButton(Decorator::Tab * tab,bool direct,BRect r,bool down)866 MacDecorator::_DrawButton(Decorator::Tab* tab, bool direct, BRect r,
867 bool down)
868 {
869 BRect rect(r);
870
871 BPoint offset(r.LeftTop()), pt2(r.RightTop());
872
873 // Topleft dark grey border
874 pt2.x--;
875 fDrawingEngine->SetHighColor(RGBColor(136, 136, 136));
876 fDrawingEngine->StrokeLine(offset, pt2);
877
878 pt2 = r.LeftBottom();
879 pt2.y--;
880 fDrawingEngine->StrokeLine(offset, pt2);
881
882 // Bottomright white border
883 offset = r.RightBottom();
884 pt2 = r.RightTop();
885 pt2.y++;
886 fDrawingEngine->SetHighColor(RGBColor(255, 255, 255));
887 fDrawingEngine->StrokeLine(offset, pt2);
888
889 pt2 = r.LeftBottom();
890 pt2.x++;
891 fDrawingEngine->StrokeLine(offset, pt2);
892
893 // Black outline
894 rect.InsetBy(1, 1);
895 fDrawingEngine->SetHighColor(RGBColor(33, 33, 33));
896 fDrawingEngine->StrokeRect(rect);
897
898 // Double-shaded button
899 rect.InsetBy(1, 1);
900 fDrawingEngine->SetHighColor(RGBColor(140, 140, 140));
901 fDrawingEngine->StrokeLine(rect.RightBottom(), rect.RightTop());
902 fDrawingEngine->StrokeLine(rect.RightBottom(), rect.LeftBottom());
903 fDrawingEngine->SetHighColor(RGBColor(206, 206, 206));
904 fDrawingEngine->StrokeLine(rect.LeftBottom(), rect.LeftTop());
905 fDrawingEngine->StrokeLine(rect.LeftTop(), rect.RightTop());
906 fDrawingEngine->SetHighColor(RGBColor(255, 255, 255));
907 fDrawingEngine->StrokeLine(rect.LeftTop(), rect.LeftTop());
908
909 rect.InsetBy(1, 1);
910 _DrawBlendedRect(fDrawingEngine, rect, !down);
911 }
912
913
914 /*! \brief Draws a rectangle with a gradient.
915 \param down The rectangle should be drawn recessed or not
916 */
917 void
_DrawBlendedRect(DrawingEngine * engine,BRect rect,bool down)918 MacDecorator::_DrawBlendedRect(DrawingEngine* engine, BRect rect,
919 bool down/*, bool focus*/)
920 {
921 // figure out which colors to use
922 rgb_color startColor, endColor;
923 if (down) {
924 startColor = fButtonLowColor;
925 endColor = fFrameHighColor;
926 } else {
927 startColor = fButtonHighColor;
928 endColor = fFrameLowerColor;
929 }
930
931 // fill
932 BGradientLinear gradient;
933 gradient.SetStart(rect.LeftTop());
934 gradient.SetEnd(rect.RightBottom());
935 gradient.AddColor(startColor, 0);
936 gradient.AddColor(endColor, 255);
937
938 engine->FillRect(rect, gradient);
939 }
940
941
942 // #pragma mark - DecorAddOn
943
944
945 extern "C" DecorAddOn*
instantiate_decor_addon(image_id id,const char * name)946 instantiate_decor_addon(image_id id, const char* name)
947 {
948 return new (std::nothrow)MacDecorAddOn(id, name);
949 }
950