xref: /haiku/src/kits/shared/ToolBar.cpp (revision 21258e2674226d6aa732321b6f8494841895af5f)
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