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