1/*
2 * Copyright 2000, Georges-Edouard Berenger. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
5
6#include "ThreadBarMenuItem.h"
7
8#include "Colors.h"
9#include "PriorityMenu.h"
10#include "ProcessController.h"
11#include "Utilities.h"
12
13#include <stdio.h>
14
15
16ThreadBarMenuItem::ThreadBarMenuItem(const char* title, thread_id thread,
17		BMenu *menu, BMessage* msg)
18	: BMenuItem(menu, msg), fThreadID(thread)
19{
20	SetLabel(title);
21	get_thread_info(fThreadID, &fThreadInfo);
22	fLastTime = system_time();
23	fKernel = -1;
24	fGrenze1 = -1;
25	fGrenze2 = -1;
26}
27
28
29void
30ThreadBarMenuItem::DrawContent()
31{
32	if (fKernel < 0)
33		BarUpdate();
34	DrawBar(true);
35	Menu()->MovePenTo(ContentLocation());
36	BMenuItem::DrawContent();
37}
38
39
40void
41ThreadBarMenuItem::DrawBar(bool force)
42{
43	bool selected = IsSelected();
44	BRect frame = Frame();
45	BMenu* menu = Menu();
46	rgb_color highColor = menu->HighColor();
47
48	BFont font;
49	menu->GetFont(&font);
50	frame = bar_rect(frame, &font);
51
52	if (fKernel < 0)
53		return;
54
55	if (fGrenze1 < 0)
56		force = true;
57
58	if (force) {
59		if (selected)
60			menu->SetHighColor(gFrameColorSelected);
61		else
62			menu->SetHighColor(gFrameColor);
63		menu->StrokeRect(frame);
64	}
65
66	frame.InsetBy(1, 1);
67	BRect r = frame;
68	float grenze1 = frame.left + (frame.right - frame.left) * fKernel;
69	float grenze2 = frame.left + (frame.right - frame.left) * (fKernel + fUser);
70	if (grenze1 > frame.right)
71		grenze1 = frame.right;
72	if (grenze2 > frame.right)
73		grenze2 = frame.right;
74	r.right = grenze1;
75
76	if (!force)
77		r.left = fGrenze1;
78
79	if (r.left < r.right) {
80		if (selected)
81			menu->SetHighColor(gKernelColorSelected);
82		else
83			menu->SetHighColor(gKernelColor);
84		menu->FillRect(r);
85	}
86
87	r.left = grenze1;
88	r.right = grenze2;
89	if (!force) {
90		if (fGrenze2 > r.left && r.left >= fGrenze1)
91			r.left = fGrenze2;
92		if (fGrenze1 < r.right && r.right  <=  fGrenze2)
93			r.right = fGrenze1;
94	}
95	if (r.left < r.right) {
96		thread_info threadInfo;
97		bool idleThread = false;
98		if (get_thread_info(fThreadID, &threadInfo) == B_OK)
99			idleThread = threadInfo.priority == B_IDLE_PRIORITY;
100
101		if (selected) {
102			menu->SetHighColor(
103				idleThread ? gIdleColorSelected : gUserColorSelected);
104		} else
105			menu->SetHighColor(idleThread ? gIdleColor : gUserColor);
106		menu->FillRect(r);
107	}
108	r.left = grenze2;
109	r.right = frame.right;
110	if (!force)
111		r.right = fGrenze2;
112	if (r.left < r.right) {
113		if (selected)
114			menu->SetHighColor(gWhiteSelected);
115		else
116			menu->SetHighColor(kWhite);
117		menu->FillRect(r);
118	}
119	menu->SetHighColor(highColor);
120	fGrenze1 = grenze1;
121	fGrenze2 = grenze2;
122}
123
124
125void
126ThreadBarMenuItem::GetContentSize(float* width, float* height)
127{
128	BMenuItem::GetContentSize(width, height);
129	*width += 10 + kBarWidth;
130}
131
132
133void
134ThreadBarMenuItem::Highlight(bool on)
135{
136	if (on) {
137		PriorityMenu* popup = (PriorityMenu*)Submenu();
138		if (popup)
139			popup->Update(fThreadInfo.priority);
140	}
141	BMenuItem::Highlight(on);
142}
143
144
145void
146ThreadBarMenuItem::BarUpdate()
147{
148	thread_info info;
149	if (get_thread_info(fThreadID, &info) == B_OK) {
150		bigtime_t now = system_time();
151		fKernel = double(info.kernel_time - fThreadInfo.kernel_time) / double(now - fLastTime);
152		fUser = double(info.user_time - fThreadInfo.user_time) / double(now - fLastTime);
153		if (info.priority == B_IDLE_PRIORITY) {
154			fUser += fKernel;
155			fKernel = 0;
156		}
157		fThreadInfo.user_time = info.user_time;
158		fThreadInfo.kernel_time = info.kernel_time;
159		fLastTime = now;
160		if (IsSelected ()) {
161			PriorityMenu* popup = (PriorityMenu*)Submenu();
162			if (popup && info.priority != fThreadInfo.priority)
163				popup->Update (info.priority);
164		}
165		fThreadInfo.priority = info.priority;
166	} else
167		fKernel = -1;
168}
169