xref: /haiku/src/kits/shared/ToolBar.cpp (revision fdc32a38447b489450b0f816219fcc0bd65a70b2)
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, const char* text, bool lockable)
87 {
88 	AddAction(new BMessage(command), target, icon, toolTipText, text, lockable);
89 }
90 
91 
92 void
93 BToolBar::AddAction(BMessage* message, BHandler* target,
94 	const BBitmap* icon, const char* toolTipText, const char* text,
95 	bool lockable)
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 	if (text != NULL)
107 		button->SetLabel(text);
108 	AddView(button);
109 	button->SetTarget(target);
110 }
111 
112 
113 void
114 BToolBar::AddSeparator()
115 {
116 	orientation ont = (fOrientation == B_HORIZONTAL) ?
117 		B_VERTICAL : B_HORIZONTAL;
118 	AddView(new BSeparatorView(ont, B_PLAIN_BORDER));
119 }
120 
121 
122 void
123 BToolBar::AddGlue()
124 {
125 	GroupLayout()->AddItem(BSpaceLayoutItem::CreateGlue());
126 }
127 
128 
129 void
130 BToolBar::AddView(BView* view)
131 {
132 	GroupLayout()->AddView(view);
133 }
134 
135 
136 void
137 BToolBar::SetActionEnabled(uint32 command, bool enabled)
138 {
139 	if (BButton* button = _FindButton(command))
140 		button->SetEnabled(enabled);
141 }
142 
143 
144 void
145 BToolBar::SetActionPressed(uint32 command, bool pressed)
146 {
147 	if (BButton* button = _FindButton(command))
148 		button->SetValue(pressed);
149 }
150 
151 
152 void
153 BToolBar::SetActionVisible(uint32 command, bool visible)
154 {
155 	BButton* button = _FindButton(command);
156 	if (button == NULL)
157 		return;
158 	for (int32 i = 0; BLayoutItem* item = GroupLayout()->ItemAt(i); i++) {
159 		if (item->View() != button)
160 			continue;
161 		item->SetVisible(visible);
162 		break;
163 	}
164 }
165 
166 
167 // #pragma mark - Private methods
168 
169 
170 void
171 BToolBar::Pulse()
172 {
173 	// TODO: Perhaps this could/should be addressed in BView instead.
174 	if (IsHidden())
175 		_HideToolTips();
176 }
177 
178 
179 void
180 BToolBar::FrameResized(float width, float height)
181 {
182 	// TODO: There seems to be a bug in app_server which does not
183 	// correctly trigger invalidation of views which are shown, when
184 	// the resulting dirty area is somehow already part of an update region.
185 	Invalidate();
186 }
187 
188 
189 void
190 BToolBar::_Init()
191 {
192 	float inset = ceilf(be_control_look->DefaultItemSpacing() / 2);
193 	GroupLayout()->SetInsets(inset, 0, inset, 0);
194 	GroupLayout()->SetSpacing(1);
195 
196 	SetFlags(Flags() | B_FRAME_EVENTS | B_PULSE_NEEDED);
197 }
198 
199 
200 BButton*
201 BToolBar::_FindButton(uint32 command) const
202 {
203 	for (int32 i = 0; BView* view = ChildAt(i); i++) {
204 		BButton* button = dynamic_cast<BButton*>(view);
205 		if (button == NULL)
206 			continue;
207 		BMessage* message = button->Message();
208 		if (message == NULL)
209 			continue;
210 		if (message->what == command) {
211 			return button;
212 			// Assumes there is only one button with this message...
213 			break;
214 		}
215 	}
216 	return NULL;
217 }
218 
219 
220 void
221 BToolBar::_HideToolTips() const
222 {
223 	for (int32 i = 0; BView* view = ChildAt(i); i++)
224 		view->HideToolTip();
225 }
226 
227 
228 } // namespace BPrivate
229