2 * Copyright 2003-2013 Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
7 * Axel Dörfler, axeld@pinc-software.de
10 #include "ScreenCornerSelector.h"
20 #include "Constants.h"
24 static const float kAspectRatio
= 4.0f
/ 3.0f
;
25 static const float kMonitorBorderSize
= 3.0f
;
26 static const float kArrowSize
= 11.0f
;
27 static const float kStopSize
= 15.0f
;
30 ScreenCornerSelector::ScreenCornerSelector(BRect frame
, const char* name
,
31 BMessage
* message
, uint32 resizingMode
)
33 BControl(frame
, name
, NULL
, message
, resizingMode
,
34 B_WILL_DRAW
| B_NAVIGABLE
| B_FULL_UPDATE_ON_RESIZE
),
35 fCurrentCorner(NO_CORNER
),
38 SetViewUIColor(B_PANEL_BACKGROUND_COLOR
);
43 ScreenCornerSelector::_MonitorFrame() const
45 float width
= Bounds().Width();
46 float height
= Bounds().Height();
48 if (width
/ kAspectRatio
> height
)
49 width
= height
* kAspectRatio
;
50 else if (height
* kAspectRatio
> width
)
51 height
= width
/ kAspectRatio
;
53 return BRect((Bounds().Width() - width
) / 2,
54 (Bounds().Height() - height
) / 2,
55 (Bounds().Width() + width
) / 2, (Bounds().Height() + height
) / 2);
60 ScreenCornerSelector::_InnerFrame(BRect monitorFrame
) const
62 return monitorFrame
.InsetByCopy(kMonitorBorderSize
+ 3,
63 kMonitorBorderSize
+ 3);
68 ScreenCornerSelector::_CenterFrame(BRect innerFrame
) const
70 return innerFrame
.InsetByCopy(kArrowSize
, kArrowSize
);
75 ScreenCornerSelector::Draw(BRect updateRect
)
77 rgb_color darkColor
= {160, 160, 160, 255};
78 rgb_color blackColor
= {0, 0, 0, 255};
79 rgb_color redColor
= {228, 0, 0, 255};
81 BRect outerRect
= _MonitorFrame();
82 BRect
innerRect(outerRect
.InsetByCopy(kMonitorBorderSize
+ 2,
83 kMonitorBorderSize
+ 2));
85 SetDrawingMode(B_OP_OVER
);
87 if (!_InnerFrame(outerRect
).Contains(updateRect
)) {
90 // if the focus is changing, we don't redraw the whole view, but only
91 // the part that's affected by the change
92 if (!IsFocusChanging()) {
93 SetHighColor(darkColor
);
94 FillRoundRect(outerRect
, kMonitorBorderSize
* 3 / 2,
95 kMonitorBorderSize
* 3 / 2);
98 if (IsFocus() && Window()->IsActive())
99 SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR
));
101 SetHighColor(blackColor
);
103 StrokeRoundRect(outerRect
, kMonitorBorderSize
* 3 / 2,
104 kMonitorBorderSize
* 3 / 2);
106 if (IsFocusChanging())
111 SetHighColor(redColor
);
112 BPoint
powerPos(outerRect
.left
+ kMonitorBorderSize
* 2, outerRect
.bottom
113 - kMonitorBorderSize
);
114 StrokeLine(powerPos
, BPoint(powerPos
.x
+ 2, powerPos
.y
));
117 if (!IsFocusChanging()) {
118 SetHighColor(210, 210, 255);
119 FillRoundRect(innerRect
, kMonitorBorderSize
, kMonitorBorderSize
);
122 if (IsFocus() && Window()->IsActive())
123 SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR
));
125 SetHighColor(blackColor
);
126 StrokeRoundRect(innerRect
, kMonitorBorderSize
, kMonitorBorderSize
);
128 innerRect
= _InnerFrame(outerRect
);
130 if (fCurrentCorner
!= NO_CORNER
)
131 _DrawArrow(innerRect
);
133 _DrawStop(innerRect
);
135 SetDrawingMode(B_OP_COPY
);
140 ScreenCornerSelector::Value()
142 return (int32
)fCurrentCorner
;
147 ScreenCornerSelector::SetValue(int32 corner
)
151 case UP_RIGHT_CORNER
:
152 case DOWN_LEFT_CORNER
:
153 case DOWN_RIGHT_CORNER
:
160 if ((screen_corner
)corner
== fCurrentCorner
)
163 fCurrentCorner
= (screen_corner
)corner
;
164 Invalidate(_InnerFrame(_MonitorFrame()));
170 ScreenCornerSelector::Corner() const
172 return fCurrentCorner
;
177 ScreenCornerSelector::SetCorner(screen_corner corner
)
179 // redirected to SetValue() to make sure only valid values are set
180 SetValue((int32
)corner
);
185 ScreenCornerSelector::_DrawStop(BRect innerFrame
)
187 BRect centerRect
= _CenterFrame(innerFrame
);
188 float size
= kStopSize
;
190 rect
.left
= centerRect
.left
+ (centerRect
.Width() - size
) / 2;
191 rect
.top
= centerRect
.top
+ (centerRect
.Height() - size
) / 2;
192 if (rect
.left
< centerRect
.left
|| rect
.top
< centerRect
.top
) {
193 size
= centerRect
.Height();
194 rect
.top
= centerRect
.top
;
195 rect
.left
= centerRect
.left
+ (centerRect
.Width() - size
) / 2;
197 rect
.right
= rect
.left
+ size
- 1;
198 rect
.bottom
= rect
.top
+ size
- 1;
200 SetHighColor(255, 0, 0);
202 SetFlags(Flags() | B_SUBPIXEL_PRECISE
);
206 size
-= sin(M_PI
/ 4) * size
+ 2;
207 rect
.InsetBy(size
, size
);
208 StrokeLine(rect
.RightTop(), rect
.LeftBottom());
210 SetFlags(Flags() & ~B_SUBPIXEL_PRECISE
);
216 ScreenCornerSelector::_DrawArrow(BRect innerFrame
)
218 float size
= kArrowSize
;
219 float sizeX
= fCurrentCorner
== UP_LEFT_CORNER
220 || fCurrentCorner
== DOWN_LEFT_CORNER
? size
: -size
;
221 float sizeY
= fCurrentCorner
== UP_LEFT_CORNER
222 || fCurrentCorner
== UP_RIGHT_CORNER
? size
: -size
;
224 innerFrame
.InsetBy(2, 2);
225 BPoint
origin(sizeX
< 0 ? innerFrame
.right
: innerFrame
.left
,
226 sizeY
< 0 ? innerFrame
.bottom
: innerFrame
.top
);
228 SetHighColor(kBlack
);
229 FillTriangle(BPoint(origin
.x
, origin
.y
), BPoint(origin
.x
, origin
.y
+ sizeY
),
230 BPoint(origin
.x
+ sizeX
, origin
.y
));
235 ScreenCornerSelector::_ScreenCorner(BPoint point
,
236 screen_corner previousCorner
) const
238 BRect innerFrame
= _InnerFrame(_MonitorFrame());
240 if (!innerFrame
.Contains(point
))
241 return previousCorner
;
243 if (_CenterFrame(innerFrame
).Contains(point
))
246 float centerX
= innerFrame
.left
+ innerFrame
.Width() / 2;
247 float centerY
= innerFrame
.top
+ innerFrame
.Height() / 2;
248 if (point
.x
< centerX
)
249 return point
.y
< centerY
? UP_LEFT_CORNER
: DOWN_LEFT_CORNER
;
251 return point
.y
< centerY
? UP_RIGHT_CORNER
: DOWN_RIGHT_CORNER
;
256 ScreenCornerSelector::MouseDown(BPoint where
)
258 fPreviousCorner
= Value();
260 SetValue(_ScreenCorner(where
, (screen_corner
)fPreviousCorner
));
261 SetMouseEventMask(B_POINTER_EVENTS
, B_NO_POINTER_HISTORY
);
266 ScreenCornerSelector::MouseUp(BPoint where
)
268 fPreviousCorner
= -1;
273 ScreenCornerSelector::MouseMoved(BPoint where
, uint32 transit
,
274 const BMessage
* dragMessage
)
276 if (fPreviousCorner
== -1)
279 SetValue(_ScreenCorner(where
, (screen_corner
)fPreviousCorner
));
284 ScreenCornerSelector::KeyDown(const char* bytes
, int32 numBytes
)
291 if (Corner() == UP_RIGHT_CORNER
)
292 SetCorner(UP_LEFT_CORNER
);
293 else if (Corner() == DOWN_RIGHT_CORNER
)
294 SetCorner(DOWN_LEFT_CORNER
);
298 if (Corner() == UP_LEFT_CORNER
)
299 SetCorner(UP_RIGHT_CORNER
);
300 else if (Corner() == DOWN_LEFT_CORNER
)
301 SetCorner(DOWN_RIGHT_CORNER
);
305 if (Corner() == DOWN_LEFT_CORNER
)
306 SetCorner(UP_LEFT_CORNER
);
307 else if (Corner() == DOWN_RIGHT_CORNER
)
308 SetCorner(UP_RIGHT_CORNER
);
312 if (Corner() == UP_LEFT_CORNER
)
313 SetCorner(DOWN_LEFT_CORNER
);
314 else if (Corner() == UP_RIGHT_CORNER
)
315 SetCorner(DOWN_RIGHT_CORNER
);
322 SetCorner(UP_LEFT_CORNER
);
326 SetCorner(UP_RIGHT_CORNER
);
330 SetCorner(DOWN_RIGHT_CORNER
);
334 SetCorner(DOWN_LEFT_CORNER
);
338 BControl::KeyDown(bytes
, numBytes
);