xref: /haiku/src/apps/processcontroller/ThreadBarMenuItem.cpp (revision 0fae96c5a349db3761ac2a4ab4a7fbbf23a3b76c)
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 
16 ThreadBarMenuItem::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 
29 void
30 ThreadBarMenuItem::DrawContent()
31 {
32 	if (fKernel < 0)
33 		BarUpdate();
34 	DrawBar(true);
35 	Menu()->MovePenTo(ContentLocation());
36 	BMenuItem::DrawContent();
37 }
38 
39 
40 void
41 ThreadBarMenuItem::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 
125 void
126 ThreadBarMenuItem::GetContentSize(float* width, float* height)
127 {
128 	BMenuItem::GetContentSize(width, height);
129 	*width += 10 + kBarWidth;
130 }
131 
132 
133 void
134 ThreadBarMenuItem::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 
145 void
146 ThreadBarMenuItem::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