xref: /haiku/src/preferences/appearance/FakeScrollBar.cpp (revision 68c70f9b6dc96d50f677862c579a65085dd7d300)
1928ffe6dSJohn Scipione /*
2928ffe6dSJohn Scipione  *  Copyright 2010-2012 Haiku, Inc. All rights reserved.
3928ffe6dSJohn Scipione  *  Distributed under the terms of the MIT license.
4928ffe6dSJohn Scipione  *
5928ffe6dSJohn Scipione  *	Authors:
6928ffe6dSJohn Scipione  *		DarkWyrm <bpmagic@columbus.rr.com>
7928ffe6dSJohn Scipione  *		John Scipione <jscipione@gmail.com>
8928ffe6dSJohn Scipione  */
9928ffe6dSJohn Scipione 
10928ffe6dSJohn Scipione 
11928ffe6dSJohn Scipione #include "FakeScrollBar.h"
12928ffe6dSJohn Scipione 
13928ffe6dSJohn Scipione #include <Box.h>
14928ffe6dSJohn Scipione #include <ControlLook.h>
15928ffe6dSJohn Scipione #include <Message.h>
16928ffe6dSJohn Scipione #include <ScrollBar.h>
17928ffe6dSJohn Scipione #include <Shape.h>
18928ffe6dSJohn Scipione #include <Size.h>
19928ffe6dSJohn Scipione #include <Window.h>
20928ffe6dSJohn Scipione 
21928ffe6dSJohn Scipione 
22928ffe6dSJohn Scipione typedef enum {
23928ffe6dSJohn Scipione 	ARROW_LEFT = 0,
24928ffe6dSJohn Scipione 	ARROW_RIGHT,
25928ffe6dSJohn Scipione 	ARROW_UP,
26928ffe6dSJohn Scipione 	ARROW_DOWN,
27928ffe6dSJohn Scipione 	ARROW_NONE
28928ffe6dSJohn Scipione } arrow_direction;
29928ffe6dSJohn Scipione 
30928ffe6dSJohn Scipione 
31928ffe6dSJohn Scipione FakeScrollBar::FakeScrollBar(bool drawArrows, bool doubleArrows,
32928ffe6dSJohn Scipione 	int32 knobStyle, BMessage* message)
33928ffe6dSJohn Scipione 	:
3412a7abb6SJohn Scipione 	BControl("FakeScrollBar", NULL, message, B_WILL_DRAW | B_NAVIGABLE),
35928ffe6dSJohn Scipione 	fDrawArrows(drawArrows),
36928ffe6dSJohn Scipione 	fDoubleArrows(doubleArrows),
37928ffe6dSJohn Scipione 	fKnobStyle(knobStyle)
38928ffe6dSJohn Scipione {
39928ffe6dSJohn Scipione 	SetExplicitMinSize(BSize(160, 20));
40928ffe6dSJohn Scipione 	SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 20));
41928ffe6dSJohn Scipione }
42928ffe6dSJohn Scipione 
43928ffe6dSJohn Scipione 
44928ffe6dSJohn Scipione FakeScrollBar::~FakeScrollBar(void)
45928ffe6dSJohn Scipione {
46928ffe6dSJohn Scipione }
47928ffe6dSJohn Scipione 
48928ffe6dSJohn Scipione 
49928ffe6dSJohn Scipione void
50928ffe6dSJohn Scipione FakeScrollBar::Draw(BRect updateRect)
51928ffe6dSJohn Scipione {
52928ffe6dSJohn Scipione 	BRect bounds = Bounds();
53928ffe6dSJohn Scipione 
54928ffe6dSJohn Scipione 	rgb_color normal = ui_color(B_PANEL_BACKGROUND_COLOR);
55928ffe6dSJohn Scipione 
5612a7abb6SJohn Scipione 	if (IsFocus()) {
5712a7abb6SJohn Scipione 		// draw the focus indicator
5812a7abb6SJohn Scipione 		SetHighColor(ui_color(B_NAVIGATION_BASE_COLOR));
5912a7abb6SJohn Scipione 		StrokeRect(bounds);
6012a7abb6SJohn Scipione 		bounds.InsetBy(1.0, 1.0);
6112a7abb6SJohn Scipione 
6212a7abb6SJohn Scipione 		// Draw the selected border (1px)
63928ffe6dSJohn Scipione 		if (Value() == B_CONTROL_ON)
64928ffe6dSJohn Scipione 			SetHighColor(ui_color(B_CONTROL_MARK_COLOR));
65928ffe6dSJohn Scipione 		else
66928ffe6dSJohn Scipione 			SetHighColor(normal);
67928ffe6dSJohn Scipione 
6812a7abb6SJohn Scipione 		StrokeRect(bounds);
6912a7abb6SJohn Scipione 		bounds.InsetBy(1.0, 1.0);
7012a7abb6SJohn Scipione 	} else {
71928ffe6dSJohn Scipione 		// Draw the selected border (2px)
7212a7abb6SJohn Scipione 		if (Value() == B_CONTROL_ON)
7312a7abb6SJohn Scipione 			SetHighColor(ui_color(B_CONTROL_MARK_COLOR));
7412a7abb6SJohn Scipione 		else
7512a7abb6SJohn Scipione 			SetHighColor(normal);
7612a7abb6SJohn Scipione 
77928ffe6dSJohn Scipione 		StrokeRect(bounds);
78928ffe6dSJohn Scipione 		bounds.InsetBy(1.0, 1.0);
79928ffe6dSJohn Scipione 		StrokeRect(bounds);
80928ffe6dSJohn Scipione 		bounds.InsetBy(1.0, 1.0);
8112a7abb6SJohn Scipione 	}
82928ffe6dSJohn Scipione 
83928ffe6dSJohn Scipione 	// draw a gap (1px)
84928ffe6dSJohn Scipione 	SetHighColor(normal);
85928ffe6dSJohn Scipione 	StrokeRect(bounds);
86928ffe6dSJohn Scipione 	bounds.InsetBy(1.0, 1.0);
87928ffe6dSJohn Scipione 
88928ffe6dSJohn Scipione 	// draw a border around control (1px)
89928ffe6dSJohn Scipione 	SetHighColor(tint_color(normal, B_DARKEN_1_TINT));
90928ffe6dSJohn Scipione 	StrokeRect(bounds);
91928ffe6dSJohn Scipione 	bounds.InsetBy(1.0, 1.0);
92928ffe6dSJohn Scipione 
93928ffe6dSJohn Scipione 	BRect thumbBG = bounds;
94928ffe6dSJohn Scipione 	BRect bgRect = bounds;
95928ffe6dSJohn Scipione 
96928ffe6dSJohn Scipione 	if (fDrawArrows) {
97928ffe6dSJohn Scipione 		// draw arrows
98928ffe6dSJohn Scipione 		SetDrawingMode(B_OP_OVER);
99928ffe6dSJohn Scipione 
100928ffe6dSJohn Scipione 		BRect buttonFrame(bounds.left, bounds.top,
101928ffe6dSJohn Scipione 			bounds.left + bounds.Height(), bounds.bottom);
102928ffe6dSJohn Scipione 
103928ffe6dSJohn Scipione 		_DrawArrowButton(ARROW_LEFT, fDoubleArrows, buttonFrame, updateRect);
104928ffe6dSJohn Scipione 
105928ffe6dSJohn Scipione 		if (fDoubleArrows) {
106928ffe6dSJohn Scipione 			buttonFrame.OffsetBy(bounds.Height() + 1, 0.0);
107928ffe6dSJohn Scipione 			_DrawArrowButton(ARROW_RIGHT, fDoubleArrows, buttonFrame,
108928ffe6dSJohn Scipione 				updateRect);
109928ffe6dSJohn Scipione 
110928ffe6dSJohn Scipione 			buttonFrame.OffsetTo(bounds.right - ((bounds.Height() * 2) + 1),
111928ffe6dSJohn Scipione 				bounds.top);
112928ffe6dSJohn Scipione 			_DrawArrowButton(ARROW_LEFT, fDoubleArrows, buttonFrame,
113928ffe6dSJohn Scipione 				updateRect);
114928ffe6dSJohn Scipione 
115928ffe6dSJohn Scipione 			thumbBG.left += bounds.Height() * 2 + 2;
116928ffe6dSJohn Scipione 			thumbBG.right -= bounds.Height() * 2 + 2;
117928ffe6dSJohn Scipione 		} else {
118928ffe6dSJohn Scipione 			thumbBG.left += bounds.Height() + 1;
119928ffe6dSJohn Scipione 			thumbBG.right -= bounds.Height() + 1;
120928ffe6dSJohn Scipione 		}
121928ffe6dSJohn Scipione 
122928ffe6dSJohn Scipione 		buttonFrame.OffsetTo(bounds.right - bounds.Height(), bounds.top);
123928ffe6dSJohn Scipione 		_DrawArrowButton(ARROW_RIGHT, fDoubleArrows, buttonFrame, updateRect);
124928ffe6dSJohn Scipione 
125928ffe6dSJohn Scipione 		SetDrawingMode(B_OP_COPY);
126928ffe6dSJohn Scipione 
127928ffe6dSJohn Scipione 		bgRect = bounds.InsetByCopy(48, 0);
128928ffe6dSJohn Scipione 	} else
129928ffe6dSJohn Scipione 		bgRect = bounds.InsetByCopy(16, 0);
130928ffe6dSJohn Scipione 
131928ffe6dSJohn Scipione 	// fill background besides the thumb
132928ffe6dSJohn Scipione 	BRect leftOfThumb(thumbBG.left, thumbBG.top, bgRect.left - 1,
133928ffe6dSJohn Scipione 		thumbBG.bottom);
134928ffe6dSJohn Scipione 	BRect rightOfThumb(bgRect.right + 1, thumbBG.top, thumbBG.right,
135928ffe6dSJohn Scipione 		thumbBG.bottom);
136928ffe6dSJohn Scipione 
137928ffe6dSJohn Scipione 	be_control_look->DrawScrollBarBackground(this, leftOfThumb,
138928ffe6dSJohn Scipione 		rightOfThumb, updateRect, normal, 0, B_HORIZONTAL);
139928ffe6dSJohn Scipione 
140928ffe6dSJohn Scipione 	// Draw scroll thumb
141928ffe6dSJohn Scipione 
142928ffe6dSJohn Scipione 	// fill the clickable surface of the thumb
143928ffe6dSJohn Scipione 	be_control_look->DrawButtonBackground(this, bgRect, updateRect,
144928ffe6dSJohn Scipione 		normal, 0, BControlLook::B_ALL_BORDERS, B_HORIZONTAL);
145928ffe6dSJohn Scipione 
146dfa8cf8cSJohn Scipione 	if (fKnobStyle == B_KNOB_STYLE_NONE)
147928ffe6dSJohn Scipione 		return;
148928ffe6dSJohn Scipione 
149928ffe6dSJohn Scipione 	// draw the scrollbar thumb knobs
150dfa8cf8cSJohn Scipione 	bool square = fKnobStyle == B_KNOB_STYLE_DOTS;
151a4f0328eSJohn Scipione 	int32 knobWidth = 0;
152a4f0328eSJohn Scipione 	int32 knobHeight = 0;
153928ffe6dSJohn Scipione 
154928ffe6dSJohn Scipione 	if (square) {
155a4f0328eSJohn Scipione 		knobWidth = 2;
156a4f0328eSJohn Scipione 		knobHeight = 2;
157928ffe6dSJohn Scipione 	} else {
158a4f0328eSJohn Scipione 		knobWidth = 1;
159a4f0328eSJohn Scipione 		knobHeight = 3;
160928ffe6dSJohn Scipione 	}
161928ffe6dSJohn Scipione 
162928ffe6dSJohn Scipione 	float hmiddle = bgRect.Width() / 2;
163928ffe6dSJohn Scipione 	float vmiddle = bgRect.Height() / 2;
164928ffe6dSJohn Scipione 
165a4f0328eSJohn Scipione 	BRect middleKnob = BRect(bgRect.left + hmiddle - knobWidth,
166a4f0328eSJohn Scipione 		bgRect.top + vmiddle - knobHeight,
167a4f0328eSJohn Scipione 		bgRect.left + hmiddle + knobWidth,
168a4f0328eSJohn Scipione 		bgRect.top + vmiddle + knobHeight);
169928ffe6dSJohn Scipione 
170a4f0328eSJohn Scipione 	BRect leftKnob = middleKnob.OffsetByCopy(knobWidth * -4, 0);
171928ffe6dSJohn Scipione 	be_control_look->DrawButtonBackground(this, leftKnob, updateRect,
172928ffe6dSJohn Scipione 		normal, 0, BControlLook::B_ALL_BORDERS, B_HORIZONTAL);
173928ffe6dSJohn Scipione 
174a4f0328eSJohn Scipione 	BRect rightKnob = middleKnob.OffsetByCopy(knobWidth * 4, 0);
175928ffe6dSJohn Scipione 	be_control_look->DrawButtonBackground(this, rightKnob, updateRect,
176928ffe6dSJohn Scipione 		normal, 0, BControlLook::B_ALL_BORDERS, B_HORIZONTAL);
177928ffe6dSJohn Scipione 
178928ffe6dSJohn Scipione 	// draw middle knob last because it modifies middleKnob
179928ffe6dSJohn Scipione 	be_control_look->DrawButtonBackground(this, middleKnob, updateRect,
180928ffe6dSJohn Scipione 		normal, 0, BControlLook::B_ALL_BORDERS, B_HORIZONTAL);
181928ffe6dSJohn Scipione }
182928ffe6dSJohn Scipione 
183928ffe6dSJohn Scipione 
184928ffe6dSJohn Scipione void
185928ffe6dSJohn Scipione FakeScrollBar::MouseDown(BPoint point)
186928ffe6dSJohn Scipione {
187928ffe6dSJohn Scipione 	BControl::MouseDown(point);
188928ffe6dSJohn Scipione }
189928ffe6dSJohn Scipione 
190928ffe6dSJohn Scipione 
191928ffe6dSJohn Scipione void
192928ffe6dSJohn Scipione FakeScrollBar::MouseMoved(BPoint point, uint32 transit,
193928ffe6dSJohn Scipione 	const BMessage* message)
194928ffe6dSJohn Scipione {
195928ffe6dSJohn Scipione 	BControl::MouseMoved(point, transit, message);
196928ffe6dSJohn Scipione }
197928ffe6dSJohn Scipione 
198928ffe6dSJohn Scipione 
199928ffe6dSJohn Scipione void
200928ffe6dSJohn Scipione FakeScrollBar::MouseUp(BPoint point)
201928ffe6dSJohn Scipione {
202928ffe6dSJohn Scipione 	SetValue(B_CONTROL_ON);
203928ffe6dSJohn Scipione 	Invoke();
204928ffe6dSJohn Scipione 
205928ffe6dSJohn Scipione 	Invalidate();
206928ffe6dSJohn Scipione 
207928ffe6dSJohn Scipione 	BControl::MouseUp(point);
208928ffe6dSJohn Scipione }
209928ffe6dSJohn Scipione 
210928ffe6dSJohn Scipione 
211928ffe6dSJohn Scipione void
212928ffe6dSJohn Scipione FakeScrollBar::SetValue(int32 value)
213928ffe6dSJohn Scipione {
214928ffe6dSJohn Scipione 	if (value != Value()) {
215928ffe6dSJohn Scipione 		BControl::SetValueNoUpdate(value);
216928ffe6dSJohn Scipione 		Invalidate();
217928ffe6dSJohn Scipione 	}
218928ffe6dSJohn Scipione 
219928ffe6dSJohn Scipione 	if (!value)
220928ffe6dSJohn Scipione 		return;
221928ffe6dSJohn Scipione 
222928ffe6dSJohn Scipione 	BView* parent = Parent();
223928ffe6dSJohn Scipione 	BView* child = NULL;
224928ffe6dSJohn Scipione 
225928ffe6dSJohn Scipione 	if (parent != NULL) {
226928ffe6dSJohn Scipione 		// If the parent is a BBox, the group parent is the parent of the BBox
227928ffe6dSJohn Scipione 		BBox* box = dynamic_cast<BBox*>(parent);
228928ffe6dSJohn Scipione 
229928ffe6dSJohn Scipione 		if (box && box->LabelView() == this)
230928ffe6dSJohn Scipione 			parent = box->Parent();
231928ffe6dSJohn Scipione 
232928ffe6dSJohn Scipione 		if (parent != NULL) {
233928ffe6dSJohn Scipione 			BBox* box = dynamic_cast<BBox*>(parent);
234928ffe6dSJohn Scipione 
235928ffe6dSJohn Scipione 			// If the parent is a BBox, skip the label if there is one
236928ffe6dSJohn Scipione 			if (box && box->LabelView())
237928ffe6dSJohn Scipione 				child = parent->ChildAt(1);
238928ffe6dSJohn Scipione 			else
239928ffe6dSJohn Scipione 				child = parent->ChildAt(0);
240928ffe6dSJohn Scipione 		} else
241928ffe6dSJohn Scipione 			child = Window()->ChildAt(0);
242928ffe6dSJohn Scipione 	} else if (Window())
243928ffe6dSJohn Scipione 		child = Window()->ChildAt(0);
244928ffe6dSJohn Scipione 
245928ffe6dSJohn Scipione 	while (child) {
246928ffe6dSJohn Scipione 		FakeScrollBar* scrollbar = dynamic_cast<FakeScrollBar*>(child);
247928ffe6dSJohn Scipione 
248928ffe6dSJohn Scipione 		if (scrollbar != NULL && (scrollbar != this))
249928ffe6dSJohn Scipione 			scrollbar->SetValue(B_CONTROL_OFF);
250928ffe6dSJohn Scipione 		else {
251928ffe6dSJohn Scipione 			// If the child is a BBox, check if the label is a scrollbarbutton
252928ffe6dSJohn Scipione 			BBox* box = dynamic_cast<BBox*>(child);
253928ffe6dSJohn Scipione 
254928ffe6dSJohn Scipione 			if (box && box->LabelView()) {
255928ffe6dSJohn Scipione 				scrollbar = dynamic_cast<FakeScrollBar*>(box->LabelView());
256928ffe6dSJohn Scipione 
257928ffe6dSJohn Scipione 				if (scrollbar != NULL && (scrollbar != this))
258928ffe6dSJohn Scipione 					scrollbar->SetValue(B_CONTROL_OFF);
259928ffe6dSJohn Scipione 			}
260928ffe6dSJohn Scipione 		}
261928ffe6dSJohn Scipione 
262928ffe6dSJohn Scipione 		child = child->NextSibling();
263928ffe6dSJohn Scipione 	}
264928ffe6dSJohn Scipione 
265928ffe6dSJohn Scipione 	//ASSERT(Value() == B_CONTROL_ON);
266928ffe6dSJohn Scipione }
267928ffe6dSJohn Scipione 
268928ffe6dSJohn Scipione 
269928ffe6dSJohn Scipione //	#pragma mark -
270928ffe6dSJohn Scipione 
271928ffe6dSJohn Scipione 
272928ffe6dSJohn Scipione void
273*68c70f9bSJohn Scipione FakeScrollBar::SetDoubleArrows(bool doubleArrows)
274928ffe6dSJohn Scipione {
275*68c70f9bSJohn Scipione 	fDoubleArrows = doubleArrows;
276928ffe6dSJohn Scipione 	Invalidate();
277928ffe6dSJohn Scipione }
278928ffe6dSJohn Scipione 
279928ffe6dSJohn Scipione 
280928ffe6dSJohn Scipione void
281*68c70f9bSJohn Scipione FakeScrollBar::SetKnobStyle(uint32 knobStyle)
282928ffe6dSJohn Scipione {
283*68c70f9bSJohn Scipione 	fKnobStyle = knobStyle;
284928ffe6dSJohn Scipione 	Invalidate();
285928ffe6dSJohn Scipione }
286928ffe6dSJohn Scipione 
287928ffe6dSJohn Scipione 
288928ffe6dSJohn Scipione void
289928ffe6dSJohn Scipione FakeScrollBar::SetFromScrollBarInfo(const scroll_bar_info &info)
290928ffe6dSJohn Scipione {
291928ffe6dSJohn Scipione 	fDoubleArrows = info.double_arrows;
292928ffe6dSJohn Scipione 	fKnobStyle = info.knob;
293928ffe6dSJohn Scipione 	Invalidate();
294928ffe6dSJohn Scipione }
295928ffe6dSJohn Scipione 
296928ffe6dSJohn Scipione 
297928ffe6dSJohn Scipione //	#pragma mark -
298928ffe6dSJohn Scipione 
299928ffe6dSJohn Scipione 
300928ffe6dSJohn Scipione void
301928ffe6dSJohn Scipione FakeScrollBar::_DrawArrowButton(int32 direction, bool doubleArrows, BRect r,
302928ffe6dSJohn Scipione 	const BRect& updateRect)
303928ffe6dSJohn Scipione {
304928ffe6dSJohn Scipione 	if (!updateRect.Intersects(r))
305928ffe6dSJohn Scipione 		return;
306928ffe6dSJohn Scipione 
307928ffe6dSJohn Scipione 	rgb_color c = ui_color(B_PANEL_BACKGROUND_COLOR);
308928ffe6dSJohn Scipione 	rgb_color light = tint_color(c, B_LIGHTEN_MAX_TINT);
309928ffe6dSJohn Scipione 	rgb_color dark = tint_color(c, B_DARKEN_1_TINT);
310928ffe6dSJohn Scipione 	rgb_color darker = tint_color(c, B_DARKEN_2_TINT);
311928ffe6dSJohn Scipione 	rgb_color normal = c;
312928ffe6dSJohn Scipione 	rgb_color arrow = tint_color(c,
313928ffe6dSJohn Scipione 		(B_DARKEN_MAX_TINT + B_DARKEN_4_TINT) / 2.0);
314928ffe6dSJohn Scipione 
315928ffe6dSJohn Scipione 	BPoint tri1, tri2, tri3;
316928ffe6dSJohn Scipione 	float hInset = r.Width() / 3;
317928ffe6dSJohn Scipione 	float vInset = r.Height() / 3;
318928ffe6dSJohn Scipione 	r.InsetBy(hInset, vInset);
319928ffe6dSJohn Scipione 
320928ffe6dSJohn Scipione 	switch (direction) {
321928ffe6dSJohn Scipione 		case ARROW_LEFT:
322928ffe6dSJohn Scipione 			tri1.Set(r.right, r.top);
323928ffe6dSJohn Scipione 			tri2.Set(r.right - r.Width() / 1.33, (r.top + r.bottom + 1) / 2);
324928ffe6dSJohn Scipione 			tri3.Set(r.right, r.bottom + 1);
325928ffe6dSJohn Scipione 			break;
326928ffe6dSJohn Scipione 
327928ffe6dSJohn Scipione 		case ARROW_RIGHT:
328928ffe6dSJohn Scipione 			tri1.Set(r.left, r.bottom + 1);
329928ffe6dSJohn Scipione 			tri2.Set(r.left + r.Width() / 1.33, (r.top + r.bottom + 1) / 2);
330928ffe6dSJohn Scipione 			tri3.Set(r.left, r.top);
331928ffe6dSJohn Scipione 			break;
332928ffe6dSJohn Scipione 
333928ffe6dSJohn Scipione 		case ARROW_UP:
334928ffe6dSJohn Scipione 			tri1.Set(r.left, r.bottom);
335928ffe6dSJohn Scipione 			tri2.Set((r.left + r.right + 1) / 2, r.bottom - r.Height() / 1.33);
336928ffe6dSJohn Scipione 			tri3.Set(r.right + 1, r.bottom);
337928ffe6dSJohn Scipione 			break;
338928ffe6dSJohn Scipione 
339928ffe6dSJohn Scipione 		default:
340928ffe6dSJohn Scipione 			tri1.Set(r.left, r.top);
341928ffe6dSJohn Scipione 			tri2.Set((r.left + r.right + 1) / 2, r.top + r.Height() / 1.33);
342928ffe6dSJohn Scipione 			tri3.Set(r.right + 1, r.top);
343928ffe6dSJohn Scipione 			break;
344928ffe6dSJohn Scipione 	}
345928ffe6dSJohn Scipione 
346928ffe6dSJohn Scipione 	r.InsetBy(-(hInset - 1), -(vInset - 1));
347928ffe6dSJohn Scipione 	BRect temp(r.InsetByCopy(-1, -1));
348928ffe6dSJohn Scipione 	be_control_look->DrawButtonBackground(this, temp, updateRect,
349928ffe6dSJohn Scipione 		normal, 0, BControlLook::B_ALL_BORDERS, B_HORIZONTAL);
350928ffe6dSJohn Scipione 
351928ffe6dSJohn Scipione 	BShape arrowShape;
352928ffe6dSJohn Scipione 	arrowShape.MoveTo(tri1);
353928ffe6dSJohn Scipione 	arrowShape.LineTo(tri2);
354928ffe6dSJohn Scipione 	arrowShape.LineTo(tri3);
355928ffe6dSJohn Scipione 
356928ffe6dSJohn Scipione 	SetHighColor(arrow);
357928ffe6dSJohn Scipione 	SetPenSize(ceilf(hInset / 2.0));
358928ffe6dSJohn Scipione 	StrokeShape(&arrowShape);
359928ffe6dSJohn Scipione 	SetPenSize(1.0);
360928ffe6dSJohn Scipione }
361