tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / preferences / mouse / MouseView.cpp
blob8cae6f2e9ac04a421535253f1bb3e54a0c6f1ec5
1 /*
2 * Copyright 2003-2015 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Jérôme Duval,
7 * Axel Dörfler (axeld@pinc-software.de)
8 * Andrew McCall (mccall@digitalparadise.co.uk)
9 * Philippe Saint-Pierre stpere@gmail.com
13 #include "MouseView.h"
15 #include <Box.h>
16 #include <Button.h>
17 #include <Debug.h>
18 #include <GradientLinear.h>
19 #include <GradientRadial.h>
20 #include <MenuField.h>
21 #include <MenuItem.h>
22 #include <PopUpMenu.h>
23 #include <Region.h>
24 #include <Shape.h>
25 #include <Slider.h>
26 #include <TextControl.h>
27 #include <TranslationUtils.h>
28 #include <TranslatorFormats.h>
29 #include <Window.h>
31 #include "MouseConstants.h"
32 #include "MouseSettings.h"
33 #include "MouseWindow.h"
36 static const int32 kButtonTop = 3;
37 static const int32 kMouseDownWidth = 72;
38 static const int32 kMouseDownHeight = 35;
40 static const int32 kOneButtonOffsets[4]
41 = { 0, kMouseDownWidth };
42 static const int32 kTwoButtonOffsets[4]
43 = { 0, kMouseDownWidth / 2, kMouseDownWidth };
44 static const int32 kThreeButtonOffsets[4]
45 = { 0, kMouseDownWidth / 3 + 1, kMouseDownWidth / 3 * 2, kMouseDownWidth };
47 static const rgb_color kButtonTextColor = { 0, 0, 0, 255 };
48 static const rgb_color kMouseShadowColor = { 100, 100, 100, 128 };
49 static const rgb_color kMouseBodyTopColor = { 0xed, 0xed, 0xed, 255 };
50 static const rgb_color kMouseBodyBottomColor = { 0x85, 0x85, 0x85, 255 };
51 static const rgb_color kMouseOutlineColor = { 0x51, 0x51, 0x51, 255 };
52 static const rgb_color kMouseButtonOutlineColor = { 0xa0, 0xa0, 0xa0, 255 };
53 static const rgb_color kButtonPressedColor = { 110, 110, 110, 110 };
56 static const int32*
57 getButtonOffsets(int32 type)
59 switch (type) {
60 case 1:
61 return kOneButtonOffsets;
62 case 2:
63 return kTwoButtonOffsets;
64 case 3:
65 default:
66 return kThreeButtonOffsets;
71 static uint32
72 getMappingNumber(int32 mapping)
74 switch (mapping) {
75 case B_PRIMARY_MOUSE_BUTTON:
76 return 0;
77 case B_SECONDARY_MOUSE_BUTTON:
78 return 1;
79 case B_TERTIARY_MOUSE_BUTTON:
80 return 2;
82 return 0;
86 // #pragma mark -
89 MouseView::MouseView(const MouseSettings &settings)
91 BView("mouse_view", B_PULSE_NEEDED | B_WILL_DRAW),
92 fSettings(settings),
93 fType(-1),
94 fButtons(0),
95 fOldButtons(0)
97 SetEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY);
101 MouseView::~MouseView()
106 void
107 MouseView::SetMouseType(int32 type)
109 fType = type;
110 Invalidate();
114 void
115 MouseView::MouseMapUpdated()
117 Invalidate();
121 void
122 MouseView::UpdateFromSettings()
124 SetMouseType(fSettings.MouseType());
128 void
129 MouseView::GetPreferredSize(float* _width, float* _height)
131 if (_width != NULL)
132 *_width = kMouseDownWidth + 2;
133 if (_height != NULL)
134 *_height = 104;
138 void
139 MouseView::AttachedToWindow()
141 if (Parent() != NULL)
142 SetViewColor(Parent()->ViewColor());
143 else
144 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
146 UpdateFromSettings();
147 _CreateButtonsPicture();
149 font_height fontHeight;
150 GetFontHeight(&fontHeight);
151 fDigitHeight = int32(ceilf(fontHeight.ascent) + ceilf(fontHeight.descent));
152 fDigitBaseline = int32(ceilf(fontHeight.ascent));
156 void
157 MouseView::MouseUp(BPoint)
159 fButtons = 0;
160 Invalidate(BRect(0, kButtonTop, kMouseDownWidth,
161 kButtonTop + kMouseDownHeight));
162 fOldButtons = fButtons;
166 void
167 MouseView::MouseDown(BPoint where)
169 BMessage *mouseMsg = Window()->CurrentMessage();
170 fButtons = mouseMsg->FindInt32("buttons");
171 int32 modifiers = mouseMsg->FindInt32("modifiers");
172 if (modifiers & B_CONTROL_KEY) {
173 if (modifiers & B_COMMAND_KEY)
174 fButtons = B_TERTIARY_MOUSE_BUTTON;
175 else
176 fButtons = B_SECONDARY_MOUSE_BUTTON;
179 // Get the current clipping region before requesting any updates.
180 // Otherwise those parts would be excluded from the region.
181 BRegion clipping;
182 GetClippingRegion(&clipping);
184 if (fOldButtons != fButtons) {
185 Invalidate(BRect(0, kButtonTop, kMouseDownWidth, kButtonTop
186 + kMouseDownHeight));
187 fOldButtons = fButtons;
190 const int32* offset = getButtonOffsets(fType);
191 int32 button = -1;
192 for (int32 i = 0; i <= fType; i++) {
193 BRect frame(offset[i], kButtonTop, offset[i + 1] - 1,
194 kButtonTop + kMouseDownHeight);
195 if (frame.Contains(where)) {
196 button = i;
197 break;
200 if (button < 0)
201 return;
203 // We are setup to receive all mouse events, even if our window
204 // is not active, so make sure that we don't display the menu when
205 // the user clicked inside our view, but another window is on top.
206 if (clipping.Contains(where)) {
207 button = _ConvertFromVisualOrder(button);
209 BPopUpMenu menu("Mouse Map Menu");
210 BMessage message(kMsgMouseMap);
211 message.AddInt32("button", button);
213 menu.AddItem(new BMenuItem("1", new BMessage(message)));
214 menu.AddItem(new BMenuItem("2", new BMessage(message)));
215 menu.AddItem(new BMenuItem("3", new BMessage(message)));
217 menu.ItemAt(getMappingNumber(fSettings.Mapping(button)))
218 ->SetMarked(true);
219 menu.SetTargetForItems(Window());
221 ConvertToScreen(&where);
222 menu.Go(where, true);
227 void
228 MouseView::Draw(BRect updateFrame)
230 SetDrawingMode(B_OP_ALPHA);
231 SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
232 SetScale(1.8);
234 BShape mouseShape;
235 mouseShape.MoveTo(BPoint(16, 12));
236 // left
237 BPoint control[3] = { BPoint(12, 16), BPoint(8, 64), BPoint(32, 64) };
238 mouseShape.BezierTo(control);
239 // right
240 BPoint control2[3] = { BPoint(56, 64), BPoint(52, 16), BPoint(48, 12) };
241 mouseShape.BezierTo(control2);
242 // top
243 BPoint control3[3] = { BPoint(44, 8), BPoint(20, 8), BPoint(16, 12) };
244 mouseShape.BezierTo(control3);
245 mouseShape.Close();
247 // Draw the shadow
248 SetOrigin(-17, -11);
249 SetHighColor(kMouseShadowColor);
250 FillShape(&mouseShape, B_SOLID_HIGH);
252 // Draw the body
253 SetOrigin(-21, -14);
254 BGradientRadial bodyGradient(28, 24, 128);
255 bodyGradient.AddColor(kMouseBodyTopColor, 0);
256 bodyGradient.AddColor(kMouseBodyBottomColor, 255);
258 FillShape(&mouseShape, bodyGradient);
260 // Draw the outline
261 SetPenSize(1 / 1.8);
262 SetDrawingMode(B_OP_OVER);
263 SetHighColor(kMouseOutlineColor);
265 StrokeShape(&mouseShape, B_SOLID_HIGH);
267 // bottom button border
268 BShape buttonsOutline;
269 buttonsOutline.MoveTo(BPoint(13, 27));
270 BPoint control4[] = { BPoint(18, 30), BPoint(46, 30), BPoint(51, 27) };
271 buttonsOutline.BezierTo(control4);
273 SetHighColor(kMouseButtonOutlineColor);
274 StrokeShape(&buttonsOutline, B_SOLID_HIGH);
276 SetScale(1);
277 SetOrigin(0, 0);
279 // Separator between the buttons
280 const int32* offset = getButtonOffsets(fType);
281 for (int32 i = 1; i < fType; i++) {
282 StrokeLine(BPoint(offset[i], kButtonTop),
283 BPoint(offset[i], kButtonTop + kMouseDownHeight));
286 mouse_map map;
287 fSettings.Mapping(map);
289 SetDrawingMode(B_OP_OVER);
291 if (fButtons != 0)
292 ClipToPicture(&fButtonsPicture, B_ORIGIN, false);
294 for (int32 i = 0; i < fType; i++) {
295 // draw mapping number centered over the button
297 bool pressed = (fButtons & map.button[_ConvertFromVisualOrder(i)]) != 0;
298 // is button currently pressed?
299 if (pressed) {
300 SetDrawingMode(B_OP_ALPHA);
301 SetHighColor(kButtonPressedColor);
302 FillRect(BRect(offset[i], kButtonTop, offset[i + 1] - 1,
303 kButtonTop + kMouseDownHeight));
306 BRect border(offset[i] + 1, kButtonTop + 5, offset[i + 1] - 1,
307 kButtonTop + kMouseDownHeight - 4);
308 if (i == 0)
309 border.left += 5;
310 if (i == fType - 1)
311 border.right -= 4;
313 char number[2] = {0};
314 number[0] = getMappingNumber(map.button[_ConvertFromVisualOrder(i)])
315 + '1';
317 SetDrawingMode(B_OP_OVER);
318 SetHighColor(kButtonTextColor);
319 DrawString(number, BPoint(
320 border.left + (border.Width() - StringWidth(number)) / 2,
321 border.top + fDigitBaseline
322 + (border.IntegerHeight() - fDigitHeight) / 2));
325 if (fButtons != 0)
326 ClipToPicture(NULL);
330 int32
331 MouseView::_ConvertFromVisualOrder(int32 i)
333 if (fType < 3)
334 return i;
336 switch (i) {
337 case 0:
338 default:
339 return 0;
340 case 1:
341 return 2;
342 case 2:
343 return 1;
348 void
349 MouseView::_CreateButtonsPicture()
351 BeginPicture(&fButtonsPicture);
352 SetScale(1.8);
353 SetOrigin(-21, -14);
355 BShape mouseShape;
356 mouseShape.MoveTo(BPoint(48, 12));
357 // top
358 BPoint control3[3] = { BPoint(44, 8), BPoint(20, 8), BPoint(16, 12) };
359 mouseShape.BezierTo(control3);
360 // left
361 BPoint control[3] = { BPoint(12, 16), BPoint(13, 27), BPoint(13, 27) };
362 mouseShape.BezierTo(control);
363 // bottom
364 BPoint control4[] = { BPoint(18, 30), BPoint(46, 30), BPoint(51, 27) };
365 mouseShape.BezierTo(control4);
366 // right
367 BPoint control2[3] = { BPoint(51, 27), BPoint(50, 14), BPoint(48, 12) };
368 mouseShape.BezierTo(control2);
370 mouseShape.Close();
372 SetHighColor(255, 0, 0, 255);
373 FillShape(&mouseShape, B_SOLID_HIGH);
375 EndPicture();
376 SetScale(1);