2 * Copyright 2003-2015 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
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"
18 #include <GradientLinear.h>
19 #include <GradientRadial.h>
20 #include <MenuField.h>
22 #include <PopUpMenu.h>
26 #include <TextControl.h>
27 #include <TranslationUtils.h>
28 #include <TranslatorFormats.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 };
57 getButtonOffsets(int32 type
)
61 return kOneButtonOffsets
;
63 return kTwoButtonOffsets
;
66 return kThreeButtonOffsets
;
72 getMappingNumber(int32 mapping
)
75 case B_PRIMARY_MOUSE_BUTTON
:
77 case B_SECONDARY_MOUSE_BUTTON
:
79 case B_TERTIARY_MOUSE_BUTTON
:
89 MouseView::MouseView(const MouseSettings
&settings
)
91 BView("mouse_view", B_PULSE_NEEDED
| B_WILL_DRAW
),
97 SetEventMask(B_POINTER_EVENTS
, B_NO_POINTER_HISTORY
);
101 MouseView::~MouseView()
107 MouseView::SetMouseType(int32 type
)
115 MouseView::MouseMapUpdated()
122 MouseView::UpdateFromSettings()
124 SetMouseType(fSettings
.MouseType());
129 MouseView::GetPreferredSize(float* _width
, float* _height
)
132 *_width
= kMouseDownWidth
+ 2;
139 MouseView::AttachedToWindow()
141 if (Parent() != NULL
)
142 SetViewColor(Parent()->ViewColor());
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
));
157 MouseView::MouseUp(BPoint
)
160 Invalidate(BRect(0, kButtonTop
, kMouseDownWidth
,
161 kButtonTop
+ kMouseDownHeight
));
162 fOldButtons
= fButtons
;
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
;
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.
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
);
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
)) {
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
)))
219 menu
.SetTargetForItems(Window());
221 ConvertToScreen(&where
);
222 menu
.Go(where
, true);
228 MouseView::Draw(BRect updateFrame
)
230 SetDrawingMode(B_OP_ALPHA
);
231 SetBlendingMode(B_PIXEL_ALPHA
, B_ALPHA_OVERLAY
);
235 mouseShape
.MoveTo(BPoint(16, 12));
237 BPoint control
[3] = { BPoint(12, 16), BPoint(8, 64), BPoint(32, 64) };
238 mouseShape
.BezierTo(control
);
240 BPoint control2
[3] = { BPoint(56, 64), BPoint(52, 16), BPoint(48, 12) };
241 mouseShape
.BezierTo(control2
);
243 BPoint control3
[3] = { BPoint(44, 8), BPoint(20, 8), BPoint(16, 12) };
244 mouseShape
.BezierTo(control3
);
249 SetHighColor(kMouseShadowColor
);
250 FillShape(&mouseShape
, B_SOLID_HIGH
);
254 BGradientRadial
bodyGradient(28, 24, 128);
255 bodyGradient
.AddColor(kMouseBodyTopColor
, 0);
256 bodyGradient
.AddColor(kMouseBodyBottomColor
, 255);
258 FillShape(&mouseShape
, bodyGradient
);
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
);
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
));
287 fSettings
.Mapping(map
);
289 SetDrawingMode(B_OP_OVER
);
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?
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);
313 char number
[2] = {0};
314 number
[0] = getMappingNumber(map
.button
[_ConvertFromVisualOrder(i
)])
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));
331 MouseView::_ConvertFromVisualOrder(int32 i
)
349 MouseView::_CreateButtonsPicture()
351 BeginPicture(&fButtonsPicture
);
356 mouseShape
.MoveTo(BPoint(48, 12));
358 BPoint control3
[3] = { BPoint(44, 8), BPoint(20, 8), BPoint(16, 12) };
359 mouseShape
.BezierTo(control3
);
361 BPoint control
[3] = { BPoint(12, 16), BPoint(13, 27), BPoint(13, 27) };
362 mouseShape
.BezierTo(control
);
364 BPoint control4
[] = { BPoint(18, 30), BPoint(46, 30), BPoint(51, 27) };
365 mouseShape
.BezierTo(control4
);
367 BPoint control2
[3] = { BPoint(51, 27), BPoint(50, 14), BPoint(48, 12) };
368 mouseShape
.BezierTo(control2
);
372 SetHighColor(255, 0, 0, 255);
373 FillShape(&mouseShape
, B_SOLID_HIGH
);