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