Breadcrumbbar.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibGUI/BoxLayout.h>
  7. #include <LibGUI/Breadcrumbbar.h>
  8. #include <LibGUI/Button.h>
  9. #include <LibGUI/Painter.h>
  10. #include <LibGfx/Font.h>
  11. #include <LibGfx/Palette.h>
  12. REGISTER_WIDGET(GUI, Breadcrumbbar)
  13. namespace GUI {
  14. class BreadcrumbButton : public Button {
  15. C_OBJECT(BreadcrumbButton);
  16. public:
  17. virtual ~BreadcrumbButton() override { }
  18. virtual bool is_uncheckable() const override { return false; }
  19. virtual void drop_event(DropEvent& event) override
  20. {
  21. if (on_drop)
  22. on_drop(event);
  23. }
  24. virtual void drag_enter_event(DragEvent& event) override
  25. {
  26. update();
  27. if (on_drag_enter)
  28. on_drag_enter(event);
  29. }
  30. virtual void drag_leave_event(Event&) override
  31. {
  32. update();
  33. }
  34. virtual void paint_event(PaintEvent& event) override
  35. {
  36. Button::paint_event(event);
  37. if (has_pending_drop()) {
  38. Painter painter(*this);
  39. painter.draw_rect(rect(), palette().selection(), true);
  40. }
  41. }
  42. Function<void(DropEvent&)> on_drop;
  43. Function<void(DragEvent&)> on_drag_enter;
  44. private:
  45. BreadcrumbButton() { }
  46. };
  47. Breadcrumbbar::Breadcrumbbar()
  48. {
  49. auto& layout = set_layout<HorizontalBoxLayout>();
  50. layout.set_spacing(0);
  51. }
  52. Breadcrumbbar::~Breadcrumbbar()
  53. {
  54. }
  55. void Breadcrumbbar::clear_segments()
  56. {
  57. m_segments.clear();
  58. remove_all_children();
  59. }
  60. void Breadcrumbbar::append_segment(String text, const Gfx::Bitmap* icon, String data, String tooltip)
  61. {
  62. auto& button = add<BreadcrumbButton>();
  63. button.set_button_style(Gfx::ButtonStyle::Coolbar);
  64. button.set_text(text);
  65. button.set_icon(icon);
  66. button.set_tooltip(move(tooltip));
  67. button.set_focus_policy(FocusPolicy::TabFocus);
  68. button.set_checkable(true);
  69. button.set_exclusive(true);
  70. button.on_click = [this, index = m_segments.size()](auto) {
  71. if (on_segment_click)
  72. on_segment_click(index);
  73. };
  74. button.on_drop = [this, index = m_segments.size()](auto& drop_event) {
  75. if (on_segment_drop)
  76. on_segment_drop(index, drop_event);
  77. };
  78. button.on_drag_enter = [this, index = m_segments.size()](auto& event) {
  79. if (on_segment_drag_enter)
  80. on_segment_drag_enter(index, event);
  81. };
  82. auto button_text_width = button.font().width(text);
  83. auto icon_width = icon ? icon->width() : 0;
  84. auto icon_padding = icon ? 4 : 0;
  85. button.set_fixed_size(button_text_width + icon_width + icon_padding + 16, 16 + 8);
  86. Segment segment { icon, text, data, button.make_weak_ptr<GUI::Button>() };
  87. m_segments.append(move(segment));
  88. }
  89. void Breadcrumbbar::set_selected_segment(Optional<size_t> index)
  90. {
  91. if (!index.has_value()) {
  92. for_each_child_of_type<GUI::AbstractButton>([&](auto& button) {
  93. button.set_checked(false);
  94. return IterationDecision::Continue;
  95. });
  96. return;
  97. }
  98. auto& segment = m_segments[index.value()];
  99. VERIFY(segment.button);
  100. segment.button->set_checked(true);
  101. }
  102. void Breadcrumbbar::doubleclick_event(MouseEvent& event)
  103. {
  104. if (on_doubleclick)
  105. on_doubleclick(event);
  106. }
  107. }