1 | /*
|
---|
2 | * Copyright (c) 2001-2008, Haiku, Inc.
|
---|
3 | * Distributed under the terms of the MIT license.
|
---|
4 | *
|
---|
5 | * Authors:
|
---|
6 | * Marc Flerackers (mflerackers@androme.be)
|
---|
7 | * Jérôme Duval (korli@users.berlios.de)
|
---|
8 | */
|
---|
9 | #include <TabView.h>
|
---|
10 |
|
---|
11 | #include <string.h>
|
---|
12 |
|
---|
13 | #include <List.h>
|
---|
14 | #include <Message.h>
|
---|
15 | #include <PropertyInfo.h>
|
---|
16 | #include <Rect.h>
|
---|
17 | #include <String.h>
|
---|
18 |
|
---|
19 |
|
---|
20 | static property_info sPropertyList[] = {
|
---|
21 | {
|
---|
22 | "Selection",
|
---|
23 | { B_GET_PROPERTY, B_SET_PROPERTY },
|
---|
24 | { B_DIRECT_SPECIFIER },
|
---|
25 | NULL, 0,
|
---|
26 | { B_INT32_TYPE }
|
---|
27 | },
|
---|
28 | {}
|
---|
29 | };
|
---|
30 |
|
---|
31 |
|
---|
32 |
|
---|
33 | BTab::BTab(BView *tabView)
|
---|
34 | :
|
---|
35 | fEnabled(true),
|
---|
36 | fSelected(false),
|
---|
37 | fFocus(false),
|
---|
38 | fView(tabView)
|
---|
39 | {
|
---|
40 | }
|
---|
41 |
|
---|
42 |
|
---|
43 | BTab::BTab(BMessage *archive)
|
---|
44 | :
|
---|
45 | fSelected(false),
|
---|
46 | fFocus(false),
|
---|
47 | fView(NULL)
|
---|
48 | {
|
---|
49 | bool disable;
|
---|
50 |
|
---|
51 | if (archive->FindBool("_disable", &disable) != B_OK)
|
---|
52 | SetEnabled(true);
|
---|
53 | else
|
---|
54 | SetEnabled(!disable);
|
---|
55 | }
|
---|
56 |
|
---|
57 |
|
---|
58 | BTab::~BTab()
|
---|
59 | {
|
---|
60 | if (!fView)
|
---|
61 | return;
|
---|
62 |
|
---|
63 | if (fSelected)
|
---|
64 | fView->RemoveSelf();
|
---|
65 |
|
---|
66 | delete fView;
|
---|
67 | }
|
---|
68 |
|
---|
69 |
|
---|
70 | BArchivable *
|
---|
71 | BTab::Instantiate(BMessage *archive)
|
---|
72 | {
|
---|
73 | if (validate_instantiation(archive, "BTab"))
|
---|
74 | return new BTab(archive);
|
---|
75 |
|
---|
76 | return NULL;
|
---|
77 | }
|
---|
78 |
|
---|
79 |
|
---|
80 | status_t
|
---|
81 | BTab::Archive(BMessage *archive, bool deep) const
|
---|
82 | {
|
---|
83 | status_t err = BArchivable::Archive(archive, deep);
|
---|
84 | if (err != B_OK)
|
---|
85 | return err;
|
---|
86 |
|
---|
87 | if (!fEnabled)
|
---|
88 | err = archive->AddBool("_disable", false);
|
---|
89 |
|
---|
90 | return err;
|
---|
91 | }
|
---|
92 |
|
---|
93 |
|
---|
94 | status_t
|
---|
95 | BTab::Perform(uint32 d, void *arg)
|
---|
96 | {
|
---|
97 | return BArchivable::Perform(d, arg);
|
---|
98 | }
|
---|
99 |
|
---|
100 |
|
---|
101 | const char *
|
---|
102 | BTab::Label() const
|
---|
103 | {
|
---|
104 | if (fView)
|
---|
105 | return fView->Name();
|
---|
106 | else
|
---|
107 | return NULL;
|
---|
108 | }
|
---|
109 |
|
---|
110 |
|
---|
111 | void
|
---|
112 | BTab::SetLabel(const char *label)
|
---|
113 | {
|
---|
114 | if (!label || !fView)
|
---|
115 | return;
|
---|
116 |
|
---|
117 | fView->SetName(label);
|
---|
118 | }
|
---|
119 |
|
---|
120 |
|
---|
121 | bool
|
---|
122 | BTab::IsSelected() const
|
---|
123 | {
|
---|
124 | return fSelected;
|
---|
125 | }
|
---|
126 |
|
---|
127 |
|
---|
128 | void
|
---|
129 | BTab::Select(BView *owner)
|
---|
130 | {
|
---|
131 | if (!owner || !View() || !owner->Window())
|
---|
132 | return;
|
---|
133 |
|
---|
134 | owner->AddChild(fView);
|
---|
135 | //fView->Show();
|
---|
136 |
|
---|
137 | fSelected = true;
|
---|
138 | }
|
---|
139 |
|
---|
140 |
|
---|
141 | void
|
---|
142 | BTab::Deselect()
|
---|
143 | {
|
---|
144 | if (View())
|
---|
145 | View()->RemoveSelf();
|
---|
146 |
|
---|
147 | fSelected = false;
|
---|
148 | }
|
---|
149 |
|
---|
150 |
|
---|
151 | void
|
---|
152 | BTab::SetEnabled(bool enabled)
|
---|
153 | {
|
---|
154 | fEnabled = enabled;
|
---|
155 | }
|
---|
156 |
|
---|
157 |
|
---|
158 | bool
|
---|
159 | BTab::IsEnabled() const
|
---|
160 | {
|
---|
161 | return fEnabled;
|
---|
162 | }
|
---|
163 |
|
---|
164 |
|
---|
165 | void
|
---|
166 | BTab::MakeFocus(bool inFocus)
|
---|
167 | {
|
---|
168 | fFocus = inFocus;
|
---|
169 | }
|
---|
170 |
|
---|
171 |
|
---|
172 | bool
|
---|
173 | BTab::IsFocus() const
|
---|
174 | {
|
---|
175 | return fFocus;
|
---|
176 | }
|
---|
177 |
|
---|
178 |
|
---|
179 | void
|
---|
180 | BTab::SetView(BView *view)
|
---|
181 | {
|
---|
182 | if (!view || fView == view)
|
---|
183 | return;
|
---|
184 |
|
---|
185 | if (fView != NULL) {
|
---|
186 | fView->RemoveSelf();
|
---|
187 | delete fView;
|
---|
188 | }
|
---|
189 | fView = view;
|
---|
190 | }
|
---|
191 |
|
---|
192 |
|
---|
193 | BView *
|
---|
194 | BTab::View() const
|
---|
195 | {
|
---|
196 | return fView;
|
---|
197 | }
|
---|
198 |
|
---|
199 |
|
---|
200 | void
|
---|
201 | BTab::DrawFocusMark(BView *owner, BRect frame)
|
---|
202 | {
|
---|
203 | float width = owner->StringWidth(Label());
|
---|
204 |
|
---|
205 | owner->SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR));
|
---|
206 | // TODO: remove offset
|
---|
207 | float offset = frame.Height() / 2.0;
|
---|
208 | owner->StrokeLine(BPoint((frame.left + frame.right - width + offset) / 2.0,
|
---|
209 | frame.bottom - 3),
|
---|
210 | BPoint((frame.left + frame.right + width + offset) / 2.0,
|
---|
211 | frame.bottom - 3));
|
---|
212 | }
|
---|
213 |
|
---|
214 |
|
---|
215 | void
|
---|
216 | BTab::DrawLabel(BView *owner, BRect frame)
|
---|
217 | {
|
---|
218 | if (Label() == NULL)
|
---|
219 | return;
|
---|
220 |
|
---|
221 | BString label = Label();
|
---|
222 | float frameWidth = frame.Width();
|
---|
223 | float width = owner->StringWidth(label.String());
|
---|
224 | font_height fh;
|
---|
225 |
|
---|
226 | if (width > frameWidth) {
|
---|
227 | BFont font;
|
---|
228 | owner->GetFont(&font);
|
---|
229 | font.TruncateString(&label, B_TRUNCATE_END, frameWidth);
|
---|
230 | width = frameWidth;
|
---|
231 | font.GetHeight(&fh);
|
---|
232 | } else {
|
---|
233 | owner->GetFontHeight(&fh);
|
---|
234 | }
|
---|
235 |
|
---|
236 | owner->SetHighColor(ui_color(B_CONTROL_TEXT_COLOR));
|
---|
237 | owner->DrawString(label.String(),
|
---|
238 | BPoint((frame.left + frame.right - width) / 2.0,
|
---|
239 | (frame.top + frame.bottom - fh.ascent - fh.descent) / 2.0
|
---|
240 | + fh.ascent));
|
---|
241 | }
|
---|
242 |
|
---|
243 |
|
---|
244 | void
|
---|
245 | BTab::DrawTab(BView *owner, BRect frame, tab_position position, bool full)
|
---|
246 | {
|
---|
247 | rgb_color no_tint = ui_color(B_PANEL_BACKGROUND_COLOR);
|
---|
248 | rgb_color lightenmax = tint_color(no_tint, B_LIGHTEN_MAX_TINT);
|
---|
249 | rgb_color darken2 = tint_color(no_tint, B_DARKEN_2_TINT);
|
---|
250 | rgb_color darken3 = tint_color(no_tint, B_DARKEN_3_TINT);
|
---|
251 | rgb_color darken4 = tint_color(no_tint, B_DARKEN_4_TINT);
|
---|
252 | rgb_color darkenmax = tint_color(no_tint, B_DARKEN_MAX_TINT);
|
---|
253 |
|
---|
254 | owner->SetHighColor(darkenmax);
|
---|
255 | owner->SetLowColor(no_tint);
|
---|
256 | // NOTE: "frame" goes from the beginning of the left slope to the beginning
|
---|
257 | // of the right slope - "lableFrame" is the frame between both slopes
|
---|
258 | BRect lableFrame = frame;
|
---|
259 | lableFrame.left = lableFrame.left + frame.Height() / 2.0;
|
---|
260 | DrawLabel(owner, lableFrame);
|
---|
261 |
|
---|
262 | owner->SetDrawingMode(B_OP_OVER);
|
---|
263 |
|
---|
264 | owner->BeginLineArray(12);
|
---|
265 |
|
---|
266 | int32 slopeWidth = (int32)ceilf(frame.Height() / 2.0);
|
---|
267 |
|
---|
268 | if (position != B_TAB_ANY) {
|
---|
269 | // full height left side
|
---|
270 | owner->AddLine(BPoint(frame.left, frame.bottom),
|
---|
271 | BPoint(frame.left + slopeWidth, frame.top), darken3);
|
---|
272 | owner->AddLine(BPoint(frame.left, frame.bottom + 1),
|
---|
273 | BPoint(frame.left + slopeWidth, frame.top + 1), lightenmax);
|
---|
274 | } else {
|
---|
275 | // upper half of left side
|
---|
276 | owner->AddLine(BPoint(frame.left + slopeWidth / 2,
|
---|
277 | frame.bottom - slopeWidth),
|
---|
278 | BPoint(frame.left + slopeWidth, frame.top), darken3);
|
---|
279 | owner->AddLine(BPoint(frame.left + slopeWidth / 2 + 2,
|
---|
280 | frame.bottom - slopeWidth - 1),
|
---|
281 | BPoint(frame.left + slopeWidth, frame.top + 1), lightenmax);
|
---|
282 | }
|
---|
283 |
|
---|
284 | // lines along the top
|
---|
285 | owner->AddLine(BPoint(frame.left + slopeWidth, frame.top),
|
---|
286 | BPoint(frame.right, frame.top), darken3);
|
---|
287 | owner->AddLine(BPoint(frame.left + slopeWidth, frame.top + 1),
|
---|
288 | BPoint(frame.right, frame.top + 1), lightenmax);
|
---|
289 |
|
---|
290 | if (full) {
|
---|
291 | // full height right side
|
---|
292 | owner->AddLine(BPoint(frame.right, frame.top),
|
---|
293 | BPoint(frame.right + slopeWidth + 2, frame.bottom), darken2);
|
---|
294 | owner->AddLine(BPoint(frame.right, frame.top + 1),
|
---|
295 | BPoint(frame.right + slopeWidth + 1, frame.bottom), darken4);
|
---|
296 | } else {
|
---|
297 | // upper half of right side
|
---|
298 | owner->AddLine(BPoint(frame.right, frame.top),
|
---|
299 | BPoint(frame.right + slopeWidth / 2 + 1,
|
---|
300 | frame.bottom - slopeWidth), darken2);
|
---|
301 | owner->AddLine(BPoint(frame.right, frame.top + 1),
|
---|
302 | BPoint(frame.right + slopeWidth / 2,
|
---|
303 | frame.bottom - slopeWidth), darken4);
|
---|
304 | }
|
---|
305 |
|
---|
306 | owner->EndLineArray();
|
---|
307 | }
|
---|
308 |
|
---|
309 |
|
---|
310 | void BTab::_ReservedTab1() {}
|
---|
311 | void BTab::_ReservedTab2() {}
|
---|
312 | void BTab::_ReservedTab3() {}
|
---|
313 | void BTab::_ReservedTab4() {}
|
---|
314 | void BTab::_ReservedTab5() {}
|
---|
315 | void BTab::_ReservedTab6() {}
|
---|
316 | void BTab::_ReservedTab7() {}
|
---|
317 | void BTab::_ReservedTab8() {}
|
---|
318 | void BTab::_ReservedTab9() {}
|
---|
319 | void BTab::_ReservedTab10() {}
|
---|
320 | void BTab::_ReservedTab11() {}
|
---|
321 | void BTab::_ReservedTab12() {}
|
---|
322 |
|
---|
323 | BTab &BTab::operator=(const BTab &)
|
---|
324 | {
|
---|
325 | // this is private and not functional, but exported
|
---|
326 | return *this;
|
---|
327 | }
|
---|
328 |
|
---|
329 |
|
---|
330 | // #pragma mark -
|
---|
331 |
|
---|
332 |
|
---|
333 | BTabView::BTabView(BRect frame, const char *name, button_width width,
|
---|
334 | uint32 resizingMode, uint32 flags)
|
---|
335 | : BView(frame, name, resizingMode, flags)
|
---|
336 | {
|
---|
337 | SetFont(be_bold_font);
|
---|
338 |
|
---|
339 | _InitObject();
|
---|
340 |
|
---|
341 | fTabWidthSetting = width;
|
---|
342 | }
|
---|
343 |
|
---|
344 |
|
---|
345 | BTabView::~BTabView()
|
---|
346 | {
|
---|
347 | for (int32 i = 0; i < CountTabs(); i++) {
|
---|
348 | delete TabAt(i);
|
---|
349 | }
|
---|
350 |
|
---|
351 | delete fTabList;
|
---|
352 | }
|
---|
353 |
|
---|
354 |
|
---|
355 | BTabView::BTabView(BMessage *archive)
|
---|
356 | : BView(archive),
|
---|
357 | fFocus(-1)
|
---|
358 | {
|
---|
359 | fContainerView = NULL;
|
---|
360 | fTabList = new BList;
|
---|
361 |
|
---|
362 | int16 width;
|
---|
363 |
|
---|
364 | if (archive->FindInt16("_but_width", &width) == B_OK)
|
---|
365 | fTabWidthSetting = (button_width)width;
|
---|
366 | else
|
---|
367 | fTabWidthSetting = B_WIDTH_AS_USUAL;
|
---|
368 |
|
---|
369 | if (archive->FindFloat("_high", &fTabHeight) != B_OK) {
|
---|
370 | font_height fh;
|
---|
371 | GetFontHeight(&fh);
|
---|
372 | fTabHeight = fh.ascent + fh.descent + fh.leading + 8.0f;
|
---|
373 | }
|
---|
374 |
|
---|
375 | fFocus = -1;
|
---|
376 |
|
---|
377 | if (archive->FindInt32("_sel", &fSelection) != B_OK)
|
---|
378 | fSelection = 0;
|
---|
379 |
|
---|
380 | if (fContainerView == NULL)
|
---|
381 | fContainerView = ChildAt(0);
|
---|
382 |
|
---|
383 | int32 i = 0;
|
---|
384 | BMessage tabMsg;
|
---|
385 |
|
---|
386 | while (archive->FindMessage("_l_items", i, &tabMsg) == B_OK) {
|
---|
387 | BArchivable *archivedTab = instantiate_object(&tabMsg);
|
---|
388 |
|
---|
389 | if (archivedTab) {
|
---|
390 | BTab *tab = dynamic_cast<BTab *>(archivedTab);
|
---|
391 |
|
---|
392 | BMessage viewMsg;
|
---|
393 | if (archive->FindMessage("_view_list", i, &viewMsg) == B_OK) {
|
---|
394 | BArchivable *archivedView = instantiate_object(&viewMsg);
|
---|
395 | if (archivedView)
|
---|
396 | AddTab(dynamic_cast<BView*>(archivedView), tab);
|
---|
397 | }
|
---|
398 | }
|
---|
399 |
|
---|
400 | tabMsg.MakeEmpty();
|
---|
401 | i++;
|
---|
402 | }
|
---|
403 | }
|
---|
404 |
|
---|
405 |
|
---|
406 | BArchivable *
|
---|
407 | BTabView::Instantiate(BMessage *archive)
|
---|
408 | {
|
---|
409 | if ( validate_instantiation(archive, "BTabView"))
|
---|
410 | return new BTabView(archive);
|
---|
411 |
|
---|
412 | return NULL;
|
---|
413 | }
|
---|
414 |
|
---|
415 |
|
---|
416 | status_t
|
---|
417 | BTabView::Archive(BMessage *archive, bool deep) const
|
---|
418 | {
|
---|
419 | if (CountTabs() > 0)
|
---|
420 | TabAt(Selection())->View()->RemoveSelf();
|
---|
421 |
|
---|
422 | status_t ret = BView::Archive(archive, deep);
|
---|
423 |
|
---|
424 | if (ret == B_OK)
|
---|
425 | ret = archive->AddInt16("_but_width", fTabWidthSetting);
|
---|
426 | if (ret == B_OK)
|
---|
427 | ret = archive->AddFloat("_high", fTabHeight);
|
---|
428 | if (ret == B_OK)
|
---|
429 | ret = archive->AddInt32("_sel", fSelection);
|
---|
430 |
|
---|
431 | if (ret == B_OK && deep) {
|
---|
432 | for (int32 i = 0; i < CountTabs(); i++) {
|
---|
433 | BMessage tabArchive;
|
---|
434 | BTab *tab = TabAt(i);
|
---|
435 |
|
---|
436 | if (!tab)
|
---|
437 | continue;
|
---|
438 | ret = tab->Archive(&tabArchive, true);
|
---|
439 | if (ret == B_OK)
|
---|
440 | ret = archive->AddMessage("_l_items", &tabArchive);
|
---|
441 |
|
---|
442 | if (!tab->View())
|
---|
443 | continue;
|
---|
444 |
|
---|
445 | BMessage viewArchive;
|
---|
446 | ret = tab->View()->Archive(&viewArchive, true);
|
---|
447 | if (ret == B_OK)
|
---|
448 | ret = archive->AddMessage("_view_list", &viewArchive);
|
---|
449 | }
|
---|
450 | }
|
---|
451 |
|
---|
452 | if (CountTabs() > 0) {
|
---|
453 | if (TabAt(Selection())->View() && ContainerView())
|
---|
454 | TabAt(Selection())->Select(ContainerView());
|
---|
455 | }
|
---|
456 |
|
---|
457 | return ret;
|
---|
458 | }
|
---|
459 |
|
---|
460 |
|
---|
461 | status_t
|
---|
462 | BTabView::Perform(perform_code d, void *arg)
|
---|
463 | {
|
---|
464 | return BView::Perform(d, arg);
|
---|
465 | }
|
---|
466 |
|
---|
467 |
|
---|
468 | void
|
---|
469 | BTabView::WindowActivated(bool active)
|
---|
470 | {
|
---|
471 | BView::WindowActivated(active);
|
---|
472 |
|
---|
473 | if (IsFocus())
|
---|
474 | Invalidate();
|
---|
475 | }
|
---|
476 |
|
---|
477 |
|
---|
478 | void
|
---|
479 | BTabView::AttachedToWindow()
|
---|
480 | {
|
---|
481 | BView::AttachedToWindow();
|
---|
482 |
|
---|
483 | Select(fSelection);
|
---|
484 | }
|
---|
485 |
|
---|
486 |
|
---|
487 | void
|
---|
488 | BTabView::AllAttached()
|
---|
489 | {
|
---|
490 | BView::AllAttached();
|
---|
491 | }
|
---|
492 |
|
---|
493 |
|
---|
494 | void
|
---|
495 | BTabView::AllDetached()
|
---|
496 | {
|
---|
497 | BView::AllDetached();
|
---|
498 | }
|
---|
499 |
|
---|
500 |
|
---|
501 | void
|
---|
502 | BTabView::DetachedFromWindow()
|
---|
503 | {
|
---|
504 | BView::DetachedFromWindow();
|
---|
505 | }
|
---|
506 |
|
---|
507 |
|
---|
508 | void
|
---|
509 | BTabView::MessageReceived(BMessage *message)
|
---|
510 | {
|
---|
511 | switch (message->what) {
|
---|
512 | case B_GET_PROPERTY:
|
---|
513 | case B_SET_PROPERTY:
|
---|
514 | {
|
---|
515 | BMessage reply(B_REPLY);
|
---|
516 | bool handled = false;
|
---|
517 |
|
---|
518 | BMessage specifier;
|
---|
519 | int32 index;
|
---|
520 | int32 form;
|
---|
521 | const char *property;
|
---|
522 | if (message->GetCurrentSpecifier(&index, &specifier, &form, &property) == B_OK) {
|
---|
523 | if (strcmp(property, "Selection") == 0) {
|
---|
524 | if (message->what == B_GET_PROPERTY) {
|
---|
525 | reply.AddInt32("result", fSelection);
|
---|
526 | handled = true;
|
---|
527 | } else {
|
---|
528 | // B_GET_PROPERTY
|
---|
529 | int32 selection;
|
---|
530 | if (message->FindInt32("data", &selection) == B_OK) {
|
---|
531 | Select(selection);
|
---|
532 | reply.AddInt32("error", B_OK);
|
---|
533 | handled = true;
|
---|
534 | }
|
---|
535 | }
|
---|
536 | }
|
---|
537 | }
|
---|
538 |
|
---|
539 | if (handled)
|
---|
540 | message->SendReply(&reply);
|
---|
541 | else
|
---|
542 | BView::MessageReceived(message);
|
---|
543 | break;
|
---|
544 | }
|
---|
545 |
|
---|
546 | case B_MOUSE_WHEEL_CHANGED:
|
---|
547 | {
|
---|
548 | float deltaX = 0.0f;
|
---|
549 | float deltaY = 0.0f;
|
---|
550 | message->FindFloat("be:wheel_delta_x", &deltaX);
|
---|
551 | message->FindFloat("be:wheel_delta_y", &deltaY);
|
---|
552 |
|
---|
553 | if (deltaX == 0.0f && deltaY == 0.0f)
|
---|
554 | return;
|
---|
555 |
|
---|
556 | if (deltaY == 0.0f)
|
---|
557 | deltaY = deltaX;
|
---|
558 |
|
---|
559 | int32 selection = Selection();
|
---|
560 | int32 numTabs = CountTabs();
|
---|
561 | if (deltaY > 0 && selection < numTabs - 1) {
|
---|
562 | //move to the right tab.
|
---|
563 | Select(Selection() + 1);
|
---|
564 | } else if (deltaY < 0 && selection > 0 && numTabs > 1) {
|
---|
565 | //move to the left tab.
|
---|
566 | Select(selection - 1);
|
---|
567 | }
|
---|
568 | }
|
---|
569 | default:
|
---|
570 | BView::MessageReceived(message);
|
---|
571 | break;
|
---|
572 | }
|
---|
573 | }
|
---|
574 |
|
---|
575 |
|
---|
576 | void
|
---|
577 | BTabView::FrameMoved(BPoint newLocation)
|
---|
578 | {
|
---|
579 | BView::FrameMoved(newLocation);
|
---|
580 | }
|
---|
581 |
|
---|
582 |
|
---|
583 | void
|
---|
584 | BTabView::FrameResized(float width,float height)
|
---|
585 | {
|
---|
586 | BView::FrameResized(width, height);
|
---|
587 | }
|
---|
588 |
|
---|
589 |
|
---|
590 | void
|
---|
591 | BTabView::KeyDown(const char *bytes, int32 numBytes)
|
---|
592 | {
|
---|
593 | if (IsHidden())
|
---|
594 | return;
|
---|
595 |
|
---|
596 | switch (bytes[0]) {
|
---|
597 | case B_DOWN_ARROW:
|
---|
598 | case B_LEFT_ARROW: {
|
---|
599 | int32 focus = fFocus - 1;
|
---|
600 | if (focus < 0)
|
---|
601 | focus = CountTabs() - 1;
|
---|
602 | SetFocusTab(focus, true);
|
---|
603 | break;
|
---|
604 | }
|
---|
605 |
|
---|
606 | case B_UP_ARROW:
|
---|
607 | case B_RIGHT_ARROW: {
|
---|
608 | int32 focus = fFocus + 1;
|
---|
609 | if (focus >= CountTabs())
|
---|
610 | focus = 0;
|
---|
611 | SetFocusTab(focus, true);
|
---|
612 | break;
|
---|
613 | }
|
---|
614 |
|
---|
615 | case B_RETURN:
|
---|
616 | case B_SPACE:
|
---|
617 | Select(FocusTab());
|
---|
618 | break;
|
---|
619 |
|
---|
620 | default:
|
---|
621 | BView::KeyDown(bytes, numBytes);
|
---|
622 | }
|
---|
623 | }
|
---|
624 |
|
---|
625 |
|
---|
626 | void
|
---|
627 | BTabView::MouseDown(BPoint point)
|
---|
628 | {
|
---|
629 | if (point.y > fTabHeight)
|
---|
630 | return;
|
---|
631 |
|
---|
632 | for (int32 i = 0; i < CountTabs(); i++) {
|
---|
633 | if (TabFrame(i).Contains(point)
|
---|
634 | && i != Selection()) {
|
---|
635 | Select(i);
|
---|
636 | return;
|
---|
637 | }
|
---|
638 | }
|
---|
639 |
|
---|
640 | BView::MouseDown(point);
|
---|
641 | }
|
---|
642 |
|
---|
643 |
|
---|
644 | void
|
---|
645 | BTabView::MouseUp(BPoint point)
|
---|
646 | {
|
---|
647 | BView::MouseUp(point);
|
---|
648 | }
|
---|
649 |
|
---|
650 |
|
---|
651 | void
|
---|
652 | BTabView::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
|
---|
653 | {
|
---|
654 | BView::MouseMoved(point, transit, message);
|
---|
655 | }
|
---|
656 |
|
---|
657 |
|
---|
658 | void
|
---|
659 | BTabView::Pulse()
|
---|
660 | {
|
---|
661 | BView::Pulse();
|
---|
662 | }
|
---|
663 |
|
---|
664 |
|
---|
665 | void
|
---|
666 | BTabView::Select(int32 index)
|
---|
667 | {
|
---|
668 | if (index < 0 || index >= CountTabs())
|
---|
669 | index = Selection();
|
---|
670 |
|
---|
671 | BTab *tab = TabAt(Selection());
|
---|
672 | if (tab)
|
---|
673 | tab->Deselect();
|
---|
674 |
|
---|
675 | tab = TabAt(index);
|
---|
676 | if (tab && ContainerView()) {
|
---|
677 | if (index == 0)
|
---|
678 | fTabOffset = 0.0f;
|
---|
679 | tab->Select(ContainerView());
|
---|
680 | fSelection = index;
|
---|
681 | SelectionChanged();
|
---|
682 | InvokeNotify(Message(), B_CONTROL_MODIFIED);
|
---|
683 | }
|
---|
684 |
|
---|
685 | Invalidate();
|
---|
686 |
|
---|
687 | if (index != 0 && !Bounds().Contains(TabFrame(index))){
|
---|
688 | if (!Bounds().Contains(TabFrame(index).LeftTop()))
|
---|
689 | fTabOffset += TabFrame(index).left - Bounds().left - 20.0f;
|
---|
690 | else
|
---|
691 | fTabOffset += TabFrame(index).right - Bounds().right + 20.0f;
|
---|
692 |
|
---|
693 | Invalidate();
|
---|
694 | }
|
---|
695 |
|
---|
696 | /*MakeFocus();
|
---|
697 | SetFocusTab(index, true);
|
---|
698 | FocusTab();*/
|
---|
699 | }
|
---|
700 |
|
---|
701 |
|
---|
702 | int32
|
---|
703 | BTabView::Selection() const
|
---|
704 | {
|
---|
705 | return fSelection;
|
---|
706 | }
|
---|
707 |
|
---|
708 |
|
---|
709 | void
|
---|
710 | BTabView::MakeFocus(bool focused)
|
---|
711 | {
|
---|
712 | BView::MakeFocus(focused);
|
---|
713 |
|
---|
714 | SetFocusTab(Selection(), focused);
|
---|
715 | }
|
---|
716 |
|
---|
717 |
|
---|
718 | void
|
---|
719 | BTabView::SetFocusTab(int32 tab, bool focused)
|
---|
720 | {
|
---|
721 | if (tab >= CountTabs())
|
---|
722 | tab = 0;
|
---|
723 |
|
---|
724 | if (tab < 0)
|
---|
725 | tab = CountTabs() - 1;
|
---|
726 |
|
---|
727 | if (focused) {
|
---|
728 | if (tab == fFocus)
|
---|
729 | return;
|
---|
730 |
|
---|
731 | if (fFocus != -1){
|
---|
732 | if (TabAt (fFocus) != NULL)
|
---|
733 | TabAt(fFocus)->MakeFocus(false);
|
---|
734 | Invalidate(TabFrame(fFocus));
|
---|
735 | }
|
---|
736 | if (TabAt(tab) != NULL){
|
---|
737 | TabAt(tab)->MakeFocus(true);
|
---|
738 | Invalidate(TabFrame(tab));
|
---|
739 | fFocus = tab;
|
---|
740 | }
|
---|
741 | } else if (fFocus != -1) {
|
---|
742 | TabAt(fFocus)->MakeFocus(false);
|
---|
743 | Invalidate(TabFrame(fFocus));
|
---|
744 | fFocus = -1;
|
---|
745 | }
|
---|
746 | }
|
---|
747 |
|
---|
748 |
|
---|
749 | int32
|
---|
750 | BTabView::FocusTab() const
|
---|
751 | {
|
---|
752 | return fFocus;
|
---|
753 | }
|
---|
754 |
|
---|
755 |
|
---|
756 | void
|
---|
757 | BTabView::Draw(BRect updateRect)
|
---|
758 | {
|
---|
759 | DrawBox(DrawTabs());
|
---|
760 |
|
---|
761 | if (IsFocus() && fFocus != -1)
|
---|
762 | TabAt(fFocus)->DrawFocusMark(this, TabFrame(fFocus));
|
---|
763 | }
|
---|
764 |
|
---|
765 |
|
---|
766 | BRect
|
---|
767 | BTabView::DrawTabs()
|
---|
768 | {
|
---|
769 | for (int32 i = 0; i < CountTabs(); i++) {
|
---|
770 | TabAt(i)->DrawTab(this, TabFrame(i),
|
---|
771 | i == fSelection ? B_TAB_FRONT : (i == 0) ? B_TAB_FIRST : B_TAB_ANY,
|
---|
772 | i + 1 != fSelection);
|
---|
773 | }
|
---|
774 |
|
---|
775 | if (fSelection < CountTabs())
|
---|
776 | return TabFrame(fSelection);
|
---|
777 |
|
---|
778 | return BRect();
|
---|
779 | }
|
---|
780 |
|
---|
781 |
|
---|
782 | void
|
---|
783 | BTabView::DrawBox(BRect selTabRect)
|
---|
784 | {
|
---|
785 | BRect rect = Bounds();
|
---|
786 | BRect lastTabRect = TabFrame(CountTabs() - 1);
|
---|
787 |
|
---|
788 | rgb_color noTint = ui_color(B_PANEL_BACKGROUND_COLOR);
|
---|
789 | rgb_color lightenMax = tint_color(noTint, B_LIGHTEN_MAX_TINT);
|
---|
790 | rgb_color darken1 = tint_color(noTint, B_DARKEN_1_TINT);
|
---|
791 | rgb_color darken2 = tint_color(noTint, B_DARKEN_2_TINT);
|
---|
792 | rgb_color darken4 = tint_color(noTint, B_DARKEN_4_TINT);
|
---|
793 |
|
---|
794 | BeginLineArray(12);
|
---|
795 |
|
---|
796 | int32 offset = (int32)ceilf(selTabRect.Height() / 2.0);
|
---|
797 |
|
---|
798 | // outer lines
|
---|
799 | AddLine(BPoint(rect.left, rect.bottom - 1),
|
---|
800 | BPoint(rect.left, selTabRect.bottom), darken2);
|
---|
801 | if (selTabRect.left >= rect.left + 1)
|
---|
802 | AddLine(BPoint(rect.left + 1, selTabRect.bottom),
|
---|
803 | BPoint(selTabRect.left, selTabRect.bottom), darken2);
|
---|
804 | if (lastTabRect.right + offset + 1 <= rect.right - 1)
|
---|
805 | AddLine(BPoint(lastTabRect.right + offset + 1, selTabRect.bottom),
|
---|
806 | BPoint(rect.right - 1, selTabRect.bottom), darken2);
|
---|
807 | AddLine(BPoint(rect.right, selTabRect.bottom + 2),
|
---|
808 | BPoint(rect.right, rect.bottom), darken2);
|
---|
809 | AddLine(BPoint(rect.right - 1, rect.bottom),
|
---|
810 | BPoint(rect.left + 2, rect.bottom), darken2);
|
---|
811 |
|
---|
812 | // inner lines
|
---|
813 | rect.InsetBy(1, 1);
|
---|
814 | selTabRect.bottom += 1;
|
---|
815 |
|
---|
816 | AddLine(BPoint(rect.left, rect.bottom - 2),
|
---|
817 | BPoint(rect.left, selTabRect.bottom), lightenMax);
|
---|
818 | if (selTabRect.left >= rect.left + 1)
|
---|
819 | AddLine(BPoint(rect.left + 1, selTabRect.bottom),
|
---|
820 | BPoint(selTabRect.left, selTabRect.bottom), lightenMax);
|
---|
821 | if (selTabRect.right + offset + 1 <= rect.right - 2)
|
---|
822 | AddLine(BPoint(selTabRect.right + offset + 1, selTabRect.bottom),
|
---|
823 | BPoint(rect.right - 2, selTabRect.bottom), lightenMax);
|
---|
824 | AddLine(BPoint(rect.right, selTabRect.bottom),
|
---|
825 | BPoint(rect.right, rect.bottom), darken4);
|
---|
826 | AddLine(BPoint(rect.right - 1, rect.bottom),
|
---|
827 | BPoint(rect.left, rect.bottom), darken4);
|
---|
828 |
|
---|
829 | // soft inner bevel at right/bottom
|
---|
830 | rect.right--;
|
---|
831 | rect.bottom--;
|
---|
832 |
|
---|
833 | AddLine(BPoint(rect.right, selTabRect.bottom + 1),
|
---|
834 | BPoint(rect.right, rect.bottom), darken1);
|
---|
835 | AddLine(BPoint(rect.right - 1, rect.bottom),
|
---|
836 | BPoint(rect.left + 1, rect.bottom), darken1);
|
---|
837 |
|
---|
838 | EndLineArray();
|
---|
839 | }
|
---|
840 |
|
---|
841 | #define X_OFFSET 0.0f
|
---|
842 |
|
---|
843 | BRect
|
---|
844 | BTabView::TabFrame(int32 tab_index) const
|
---|
845 | {
|
---|
846 | // TODO: fix to remove "offset" in DrawTab and DrawLabel ...
|
---|
847 | switch (fTabWidthSetting) {
|
---|
848 | case B_WIDTH_FROM_LABEL:
|
---|
849 | {
|
---|
850 | float x = 6.0f;
|
---|
851 | for (int32 i = 0; i < tab_index; i++){
|
---|
852 | x += StringWidth(TabAt(i)->Label()) + 20.0f;
|
---|
853 | }
|
---|
854 |
|
---|
855 | return BRect(x - fTabOffset, 0.0f,
|
---|
856 | x - fTabOffset + StringWidth(TabAt(tab_index)->Label()) + 20.0f , fTabHeight);
|
---|
857 |
|
---|
858 |
|
---|
859 | /*float x = X_OFFSET;
|
---|
860 | for (int32 i = 0; i < tab_index; i++)
|
---|
861 | x += StringWidth(TabAt(i)->Label()) + 20.0f;
|
---|
862 |
|
---|
863 | return BRect(x, 0.0f,
|
---|
864 | x + StringWidth(TabAt(tab_index)->Label()) + 20.0f, fTabHeight);*/
|
---|
865 | }
|
---|
866 |
|
---|
867 | case B_WIDTH_FROM_WIDEST:
|
---|
868 | {
|
---|
869 | float width = 0.0f;
|
---|
870 |
|
---|
871 | for (int32 i = 0; i < CountTabs(); i++) {
|
---|
872 | float tabWidth = StringWidth(TabAt(i)->Label()) + 20.0f;
|
---|
873 | if (tabWidth > width)
|
---|
874 | width = tabWidth;
|
---|
875 | }
|
---|
876 | return BRect((6.0f + tab_index * width) - fTabOffset, 0.0f,
|
---|
877 | (6.0f + tab_index * width + width) - fTabOffset, fTabHeight);
|
---|
878 | /*float width = 0.0f;
|
---|
879 |
|
---|
880 | for (int32 i = 0; i < CountTabs(); i++) {
|
---|
881 | float tabWidth = StringWidth(TabAt(i)->Label()) + 20.0f;
|
---|
882 |
|
---|
883 | if (tabWidth > width)
|
---|
884 | width = tabWidth;
|
---|
885 | }
|
---|
886 |
|
---|
887 | return BRect(X_OFFSET + tab_index * width, 0.0f,
|
---|
888 | X_OFFSET + tab_index * width + width, fTabHeight);*/
|
---|
889 | }
|
---|
890 |
|
---|
891 | case B_WIDTH_AS_USUAL:
|
---|
892 | default:
|
---|
893 | return BRect((6.0f + tab_index * 100.0f) - fTabOffset, 0.0f,
|
---|
894 | (6.0f + tab_index * 100.0f + 100.0f) - fTabOffset, fTabHeight);
|
---|
895 | /*return BRect(X_OFFSET + tab_index * 100.0f, 0.0f,
|
---|
896 | X_OFFSET + tab_index * 100.0f + 100.0f, fTabHeight);*/
|
---|
897 | }
|
---|
898 | }
|
---|
899 |
|
---|
900 |
|
---|
901 | void
|
---|
902 | BTabView::SetFlags(uint32 flags)
|
---|
903 | {
|
---|
904 | BView::SetFlags(flags);
|
---|
905 | }
|
---|
906 |
|
---|
907 |
|
---|
908 | void
|
---|
909 | BTabView::SetResizingMode(uint32 mode)
|
---|
910 | {
|
---|
911 | BView::SetResizingMode(mode);
|
---|
912 | }
|
---|
913 |
|
---|
914 |
|
---|
915 | void
|
---|
916 | BTabView::GetPreferredSize(float *width, float *height)
|
---|
917 | {
|
---|
918 | BView::GetPreferredSize(width, height);
|
---|
919 | }
|
---|
920 |
|
---|
921 |
|
---|
922 | void
|
---|
923 | BTabView::ResizeToPreferred()
|
---|
924 | {
|
---|
925 | BView::ResizeToPreferred();
|
---|
926 | }
|
---|
927 |
|
---|
928 |
|
---|
929 | BHandler *
|
---|
930 | BTabView::ResolveSpecifier(BMessage *message, int32 index,
|
---|
931 | BMessage *specifier, int32 what, const char *property)
|
---|
932 | {
|
---|
933 | BPropertyInfo propInfo(sPropertyList);
|
---|
934 |
|
---|
935 | if (propInfo.FindMatch(message, 0, specifier, what, property) >= B_OK)
|
---|
936 | return this;
|
---|
937 |
|
---|
938 | return BView::ResolveSpecifier(message, index, specifier, what,
|
---|
939 | property);
|
---|
940 | }
|
---|
941 |
|
---|
942 |
|
---|
943 | status_t
|
---|
944 | BTabView::GetSupportedSuites(BMessage *message)
|
---|
945 | {
|
---|
946 | message->AddString("suites", "suite/vnd.Be-tab-view");
|
---|
947 |
|
---|
948 | BPropertyInfo propInfo(sPropertyList);
|
---|
949 | message->AddFlat("messages", &propInfo);
|
---|
950 |
|
---|
951 | return BView::GetSupportedSuites(message);
|
---|
952 | }
|
---|
953 |
|
---|
954 |
|
---|
955 | void
|
---|
956 | BTabView::AddTab(BView *target, BTab *tab)
|
---|
957 | {
|
---|
958 | if (tab == NULL)
|
---|
959 | tab = new BTab(target);
|
---|
960 | else
|
---|
961 | tab->SetView(target);
|
---|
962 |
|
---|
963 | fTabList->AddItem(tab);
|
---|
964 | }
|
---|
965 |
|
---|
966 |
|
---|
967 | BTab *
|
---|
968 | BTabView::RemoveTab(int32 index)
|
---|
969 | {
|
---|
970 | if (index < 0 || index >= CountTabs())
|
---|
971 | return NULL;
|
---|
972 |
|
---|
973 | BTab *tab = (BTab *)fTabList->RemoveItem(index);
|
---|
974 | if (tab == NULL)
|
---|
975 | return NULL;
|
---|
976 |
|
---|
977 | tab->Deselect();
|
---|
978 |
|
---|
979 | if (index <= fSelection && fSelection != 0)
|
---|
980 | fSelection--;
|
---|
981 |
|
---|
982 | if (CountTabs() == 0)
|
---|
983 | fFocus = -1;
|
---|
984 | else
|
---|
985 | Select(fSelection);
|
---|
986 |
|
---|
987 | if (fFocus == CountTabs() - 1 || CountTabs() == 0)
|
---|
988 | SetFocusTab(fFocus, false);
|
---|
989 | else
|
---|
990 | SetFocusTab(fFocus, true);
|
---|
991 |
|
---|
992 | return tab;
|
---|
993 | }
|
---|
994 |
|
---|
995 |
|
---|
996 | BTab *
|
---|
997 | BTabView::TabAt(int32 index) const
|
---|
998 | {
|
---|
999 | return (BTab *)fTabList->ItemAt(index);
|
---|
1000 | }
|
---|
1001 |
|
---|
1002 |
|
---|
1003 | void
|
---|
1004 | BTabView::SetTabWidth(button_width width)
|
---|
1005 | {
|
---|
1006 | fTabWidthSetting = width;
|
---|
1007 |
|
---|
1008 | Invalidate();
|
---|
1009 | }
|
---|
1010 |
|
---|
1011 |
|
---|
1012 | button_width
|
---|
1013 | BTabView::TabWidth() const
|
---|
1014 | {
|
---|
1015 | return fTabWidthSetting;
|
---|
1016 | }
|
---|
1017 |
|
---|
1018 |
|
---|
1019 | void
|
---|
1020 | BTabView::SetTabHeight(float height)
|
---|
1021 | {
|
---|
1022 | if (fTabHeight == height)
|
---|
1023 | return;
|
---|
1024 |
|
---|
1025 | fContainerView->MoveBy(0.0f, height - fTabHeight);
|
---|
1026 | fContainerView->ResizeBy(0.0f, height - fTabHeight);
|
---|
1027 |
|
---|
1028 | fTabHeight = height;
|
---|
1029 |
|
---|
1030 | Invalidate();
|
---|
1031 | }
|
---|
1032 |
|
---|
1033 |
|
---|
1034 | float
|
---|
1035 | BTabView::TabHeight() const
|
---|
1036 | {
|
---|
1037 | return fTabHeight;
|
---|
1038 | }
|
---|
1039 |
|
---|
1040 |
|
---|
1041 | BView *
|
---|
1042 | BTabView::ContainerView() const
|
---|
1043 | {
|
---|
1044 | return fContainerView;
|
---|
1045 | }
|
---|
1046 |
|
---|
1047 |
|
---|
1048 | int32
|
---|
1049 | BTabView::CountTabs() const
|
---|
1050 | {
|
---|
1051 | return fTabList->CountItems();
|
---|
1052 | }
|
---|
1053 |
|
---|
1054 |
|
---|
1055 | BView *
|
---|
1056 | BTabView::ViewForTab(int32 tabIndex) const
|
---|
1057 | {
|
---|
1058 | BTab *tab = TabAt(tabIndex);
|
---|
1059 | if (tab)
|
---|
1060 | return tab->View();
|
---|
1061 |
|
---|
1062 | return NULL;
|
---|
1063 | }
|
---|
1064 |
|
---|
1065 |
|
---|
1066 | void
|
---|
1067 | BTabView::SetSelectionMessage(BMessage* message)
|
---|
1068 | {
|
---|
1069 | BInvoker::SetMessage(message);
|
---|
1070 | }
|
---|
1071 |
|
---|
1072 |
|
---|
1073 | BMessage*
|
---|
1074 | BTabView::SelectionMessage() const
|
---|
1075 | {
|
---|
1076 | return BInvoker::Message();
|
---|
1077 | }
|
---|
1078 |
|
---|
1079 |
|
---|
1080 | uint32
|
---|
1081 | BTabView::SelectionCommand() const
|
---|
1082 | {
|
---|
1083 | return BInvoker::Command();
|
---|
1084 | }
|
---|
1085 |
|
---|
1086 |
|
---|
1087 | void
|
---|
1088 | BTabView::SelectionChanged()
|
---|
1089 | {
|
---|
1090 | // Hook method to be implemented by subclasses
|
---|
1091 | }
|
---|
1092 |
|
---|
1093 |
|
---|
1094 | void
|
---|
1095 | BTabView::_InitObject()
|
---|
1096 | {
|
---|
1097 | fTabList = new BList;
|
---|
1098 |
|
---|
1099 | fTabWidthSetting = B_WIDTH_AS_USUAL;
|
---|
1100 | fSelection = 0;
|
---|
1101 | fFocus = -1;
|
---|
1102 | fTabOffset = 0.0f;
|
---|
1103 |
|
---|
1104 | rgb_color color = ui_color(B_PANEL_BACKGROUND_COLOR);
|
---|
1105 |
|
---|
1106 | SetViewColor(color);
|
---|
1107 | SetLowColor(color);
|
---|
1108 |
|
---|
1109 | font_height fh;
|
---|
1110 | GetFontHeight(&fh);
|
---|
1111 | fTabHeight = fh.ascent + fh.descent + fh.leading + 8.0f;
|
---|
1112 |
|
---|
1113 | BRect bounds = Bounds();
|
---|
1114 |
|
---|
1115 | bounds.top += TabHeight();
|
---|
1116 | bounds.InsetBy(3.0f, 3.0f);
|
---|
1117 |
|
---|
1118 | fContainerView = new BView(bounds, "view container", B_FOLLOW_ALL,
|
---|
1119 | B_WILL_DRAW);
|
---|
1120 |
|
---|
1121 | fContainerView->SetViewColor(color);
|
---|
1122 | fContainerView->SetLowColor(color);
|
---|
1123 |
|
---|
1124 | AddChild(fContainerView);
|
---|
1125 | }
|
---|
1126 |
|
---|
1127 |
|
---|
1128 | void BTabView::_ReservedTabView3() {}
|
---|
1129 | void BTabView::_ReservedTabView4() {}
|
---|
1130 | void BTabView::_ReservedTabView5() {}
|
---|
1131 | void BTabView::_ReservedTabView6() {}
|
---|
1132 | void BTabView::_ReservedTabView7() {}
|
---|
1133 | void BTabView::_ReservedTabView8() {}
|
---|
1134 | void BTabView::_ReservedTabView9() {}
|
---|
1135 | void BTabView::_ReservedTabView10() {}
|
---|
1136 | void BTabView::_ReservedTabView11() {}
|
---|
1137 | void BTabView::_ReservedTabView12() {}
|
---|
1138 |
|
---|
1139 |
|
---|
1140 | BTabView::BTabView(const BTabView &tabView)
|
---|
1141 | : BView(tabView)
|
---|
1142 | {
|
---|
1143 | // this is private and not functional, but exported
|
---|
1144 | }
|
---|
1145 |
|
---|
1146 |
|
---|
1147 | BTabView &BTabView::operator=(const BTabView &)
|
---|
1148 | {
|
---|
1149 | // this is private and not functional, but exported
|
---|
1150 | return *this;
|
---|
1151 | }
|
---|