1 /* 2 * Copyright 2011 Stephan Aßmus <superstippi@gmx.de> 3 * All rights reserved. Distributed under the terms of the MIT license. 4 */ 5 #include "ToolBar.h" 6 7 #include <Button.h> 8 #include <ControlLook.h> 9 #include <Message.h> 10 #include <SeparatorView.h> 11 #include <SpaceLayoutItem.h> 12 13 14 namespace BPrivate { 15 16 17 class LockableButton: public BButton { 18 public: 19 LockableButton(const char* name, const char* label, 20 BMessage* message); 21 22 void MouseDown(BPoint point); 23 }; 24 25 26 LockableButton::LockableButton(const char* name, const char* label, 27 BMessage* message) 28 : 29 BButton(name, label, message) 30 { 31 } 32 33 34 void 35 LockableButton::MouseDown(BPoint point) 36 { 37 if ((modifiers() & B_SHIFT_KEY) != 0 || Value() == B_CONTROL_ON) 38 SetBehavior(B_TOGGLE_BEHAVIOR); 39 else 40 SetBehavior(B_BUTTON_BEHAVIOR); 41 42 Message()->SetInt32("behavior", Behavior()); 43 BButton::MouseDown(point); 44 } 45 46 47 BToolBar::BToolBar(BRect frame, orientation ont) 48 : 49 BGroupView(ont), 50 fOrientation(ont) 51 { 52 _Init(); 53 54 MoveTo(frame.LeftTop()); 55 ResizeTo(frame.Width(), frame.Height()); 56 SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP); 57 } 58 59 60 BToolBar::BToolBar(orientation ont) 61 : 62 BGroupView(ont), 63 fOrientation(ont) 64 { 65 _Init(); 66 } 67 68 69 BToolBar::~BToolBar() 70 { 71 } 72 73 74 void 75 BToolBar::Hide() 76 { 77 BView::Hide(); 78 // TODO: This could be fixed in BView instead. Looking from the 79 // BButtons, they are not hidden though, only their parent is... 80 _HideToolTips(); 81 } 82 83 84 void 85 BToolBar::AddAction(uint32 command, BHandler* target, const BBitmap* icon, 86 const char* toolTipText, bool lockable) 87 { 88 AddAction(new BMessage(command), target, icon, toolTipText, lockable); 89 } 90 91 92 void 93 BToolBar::AddAction(BMessage* message, BHandler* target, 94 const BBitmap* icon, const char* toolTipText, bool lockable) 95 { 96 97 BButton* button; 98 if (lockable) 99 button = new LockableButton(NULL, NULL, message); 100 else 101 button = new BButton(NULL, NULL, message); 102 button->SetIcon(icon); 103 button->SetFlat(true); 104 if (toolTipText != NULL) 105 button->SetToolTip(toolTipText); 106 AddView(button); 107 button->SetTarget(target); 108 } 109 110 111 void 112 BToolBar::AddSeparator() 113 { 114 orientation ont = (fOrientation == B_HORIZONTAL) ? 115 B_VERTICAL : B_HORIZONTAL; 116 AddView(new BSeparatorView(ont, B_PLAIN_BORDER)); 117 } 118 119 120 void 121 BToolBar::AddGlue() 122 { 123 GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue()); 124 } 125 126 127 void 128 BToolBar::AddView(BView* view) 129 { 130 GroupLayout()->AddView(view); 131 } 132 133 134 void 135 BToolBar::SetActionEnabled(uint32 command, bool enabled) 136 { 137 if (BButton* button = _FindButton(command)) 138 button->SetEnabled(enabled); 139 } 140 141 142 void 143 BToolBar::SetActionPressed(uint32 command, bool pressed) 144 { 145 if (BButton* button = _FindButton(command)) 146 button->SetValue(pressed); 147 } 148 149 150 void 151 BToolBar::SetActionVisible(uint32 command, bool visible) 152 { 153 BButton* button = _FindButton(command); 154 if (button == NULL) 155 return; 156 for (int32 i = 0; BLayoutItem* item = GroupLayout()->ItemAt(i); i++) { 157 if (item->View() != button) 158 continue; 159 item->SetVisible(visible); 160 break; 161 } 162 } 163 164 165 // #pragma mark - Private methods 166 167 168 void 169 BToolBar::Pulse() 170 { 171 // TODO: Perhaps this could/should be addressed in BView instead. 172 if (IsHidden()) 173 _HideToolTips(); 174 } 175 176 177 void 178 BToolBar::FrameResized(float width, float height) 179 { 180 // TODO: There seems to be a bug in app_server which does not 181 // correctly trigger invalidation of views which are shown, when 182 // the resulting dirty area is somehow already part of an update region. 183 Invalidate(); 184 } 185 186 187 void 188 BToolBar::_Init() 189 { 190 float inset = ceilf(be_control_look->DefaultItemSpacing() / 2); 191 GroupLayout()->SetInsets(inset, 0, inset, 0); 192 GroupLayout()->SetSpacing(1); 193 194 SetFlags(Flags() | B_FRAME_EVENTS | B_PULSE_NEEDED); 195 } 196 197 198 BButton* 199 BToolBar::_FindButton(uint32 command) const 200 { 201 for (int32 i = 0; BView* view = ChildAt(i); i++) { 202 BButton* button = dynamic_cast<BButton*>(view); 203 if (button == NULL) 204 continue; 205 BMessage* message = button->Message(); 206 if (message == NULL) 207 continue; 208 if (message->what == command) { 209 return button; 210 // Assumes there is only one button with this message... 211 break; 212 } 213 } 214 return NULL; 215 } 216 217 218 void 219 BToolBar::_HideToolTips() const 220 { 221 for (int32 i = 0; BView* view = ChildAt(i); i++) 222 view->HideToolTip(); 223 } 224 225 226 } // namespace BPrivate 227