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 14namespace BPrivate { 15 16 17 18// Button to adopt backgrond color of toolbar 19class ToolBarButton : public BButton { 20public: 21 ToolBarButton(const char* name, const char* label, 22 BMessage* message); 23 24 void AttachedToWindow(); 25}; 26 27 28ToolBarButton::ToolBarButton(const char* name, const char* label, 29 BMessage* message) 30 : 31 BButton(name, label, message) 32 {} 33 34 35void 36ToolBarButton::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 48class LockableButton: public ToolBarButton { 49public: 50 LockableButton(const char* name, const char* label, 51 BMessage* message); 52 53 void MouseDown(BPoint point); 54}; 55 56 57LockableButton::LockableButton(const char* name, const char* label, 58 BMessage* message) 59 : 60 ToolBarButton(name, label, message) 61{ 62} 63 64 65void 66LockableButton::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 81BToolBar::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 94BToolBar::BToolBar(orientation ont) 95 : 96 BGroupView(ont), 97 fOrientation(ont) 98{ 99 _Init(); 100} 101 102 103BToolBar::~BToolBar() 104{ 105} 106 107 108void 109BToolBar::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 118void 119BToolBar::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 126void 127BToolBar::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 147void 148BToolBar::AddSeparator() 149{ 150 orientation ont = (fOrientation == B_HORIZONTAL) ? 151 B_VERTICAL : B_HORIZONTAL; 152 AddView(new BSeparatorView(ont, B_PLAIN_BORDER)); 153} 154 155 156void 157BToolBar::AddGlue() 158{ 159 GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue()); 160} 161 162 163void 164BToolBar::AddView(BView* view) 165{ 166 GroupLayout()->AddView(view); 167} 168 169 170void 171BToolBar::SetActionEnabled(uint32 command, bool enabled) 172{ 173 if (BButton* button = FindButton(command)) 174 button->SetEnabled(enabled); 175} 176 177 178void 179BToolBar::SetActionPressed(uint32 command, bool pressed) 180{ 181 if (BButton* button = FindButton(command)) 182 button->SetValue(pressed); 183} 184 185 186void 187BToolBar::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 201BButton* 202BToolBar::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 223void 224BToolBar::Pulse() 225{ 226 // TODO: Perhaps this could/should be addressed in BView instead. 227 if (IsHidden()) 228 _HideToolTips(); 229} 230 231 232void 233BToolBar::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 242void 243BToolBar::_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 253void 254BToolBar::_HideToolTips() const 255{ 256 for (int32 i = 0; BView* view = ChildAt(i); i++) 257 view->HideToolTip(); 258} 259 260 261} // namespace BPrivate 262