Squash commits for public release
This commit is contained in:
23
userland/applications/activity_monitor/AppDelegate.cpp
Normal file
23
userland/applications/activity_monitor/AppDelegate.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "ViewController.h"
|
||||
#include <libui/AppDelegate.h>
|
||||
|
||||
class AppDelegate : public UI::AppDelegate {
|
||||
public:
|
||||
AppDelegate() = default;
|
||||
virtual ~AppDelegate() = default;
|
||||
|
||||
LG::Size preferred_desktop_window_size() const override { return LG::Size(220, 210); }
|
||||
const char* icon_path() const override { return "/res/icons/apps/activity_monitor.icon"; }
|
||||
|
||||
virtual bool application() override
|
||||
{
|
||||
auto style = StatusBarStyle(LG::Color(222, 232, 227)).set_hide_text();
|
||||
auto& window = std::xos::construct<UI::Window>("Monitor", window_size(), icon_path(), style);
|
||||
auto& superview = window.create_superview<UI::View, ViewController>();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
SET_APP_DELEGATE(AppDelegate);
|
||||
16
userland/applications/activity_monitor/BUILD.gn
Normal file
16
userland/applications/activity_monitor/BUILD.gn
Normal file
@@ -0,0 +1,16 @@
|
||||
import("//build/userland/TEMPLATE.gni")
|
||||
|
||||
xOS_application("activity_monitor") {
|
||||
display_name = "Monitor"
|
||||
sources = [
|
||||
"AppDelegate.cpp",
|
||||
"GraphView.cpp",
|
||||
]
|
||||
configs = [ "//build/userland:userland_flags" ]
|
||||
deplibs = [
|
||||
"libcxx",
|
||||
"libfoundation",
|
||||
"libg",
|
||||
"libui",
|
||||
]
|
||||
}
|
||||
40
userland/applications/activity_monitor/GraphView.cpp
Normal file
40
userland/applications/activity_monitor/GraphView.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "GraphView.h"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <libfoundation/EventLoop.h>
|
||||
#include <libfoundation/KeyboardMapping.h>
|
||||
#include <libg/Color.h>
|
||||
#include <libui/Context.h>
|
||||
|
||||
GraphView::GraphView(UI::View* superview, const LG::Rect& frame, int data_size)
|
||||
: UI::View(superview, frame)
|
||||
, m_data(data_size)
|
||||
{
|
||||
for (int i = 0; i < data_size; i++) {
|
||||
m_data.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
void GraphView::display(const LG::Rect& rect)
|
||||
{
|
||||
LG::Context ctx = UI::graphics_current_context();
|
||||
ctx.add_clip(rect);
|
||||
|
||||
ctx.set_fill_color(LG::Color(233, 233, 233));
|
||||
ctx.fill(bounds());
|
||||
|
||||
ctx.set_fill_color(LG::Color(14, 72, 19));
|
||||
|
||||
size_t left_padding = bounds().width();
|
||||
size_t height = bounds().height();
|
||||
size_t column_width = 3;
|
||||
|
||||
for (int i = m_data.size() - 1; i >= 0; i--) {
|
||||
left_padding -= column_width;
|
||||
size_t column_height = (m_data[i] * height) / 100;
|
||||
ctx.fill(LG::Rect(left_padding, height - column_height, column_width, column_height));
|
||||
if (left_padding < column_width) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
userland/applications/activity_monitor/GraphView.h
Normal file
25
userland/applications/activity_monitor/GraphView.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include <libg/Font.h>
|
||||
#include <libui/View.h>
|
||||
#include <string>
|
||||
|
||||
class GraphView : public UI::View {
|
||||
UI_OBJECT();
|
||||
|
||||
public:
|
||||
GraphView(UI::View* superview, const LG::Rect&, int data_size);
|
||||
|
||||
void display(const LG::Rect& rect) override;
|
||||
|
||||
void add_new_value(int val)
|
||||
{
|
||||
for (int i = 0; i < m_data.size() - 1; i++) {
|
||||
m_data[i] = m_data[i + 1];
|
||||
}
|
||||
m_data[m_data.size() - 1] = val;
|
||||
set_needs_display();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<int> m_data;
|
||||
};
|
||||
150
userland/applications/activity_monitor/ViewController.h
Normal file
150
userland/applications/activity_monitor/ViewController.h
Normal file
@@ -0,0 +1,150 @@
|
||||
#pragma once
|
||||
#include "GraphView.h"
|
||||
#include <libfoundation/ProcessInfo.h>
|
||||
#include <libui/App.h>
|
||||
#include <libui/Button.h>
|
||||
#include <libui/Label.h>
|
||||
#include <libui/StackView.h>
|
||||
#include <libui/View.h>
|
||||
#include <libui/ViewController.h>
|
||||
#include <libui/Window.h>
|
||||
#include <memory>
|
||||
#include <sys/types.h>
|
||||
|
||||
static char buf[256];
|
||||
|
||||
class ViewController : public UI::ViewController<UI::View> {
|
||||
public:
|
||||
ViewController(UI::View& view)
|
||||
: UI::ViewController<UI::View>(view)
|
||||
, m_cpu_count(LFoundation::ProcessInfo::the().processor_count())
|
||||
{
|
||||
}
|
||||
virtual ~ViewController() = default;
|
||||
|
||||
inline int cpu_count() const { return m_cpu_count; }
|
||||
|
||||
void view_did_load() override
|
||||
{
|
||||
state.cpu_load.resize(cpu_count());
|
||||
state.cpu_old_user_time.resize(cpu_count());
|
||||
state.cpu_old_system_time.resize(cpu_count());
|
||||
state.cpu_old_idle_time.resize(cpu_count());
|
||||
|
||||
view().set_background_color(LG::Color::LightSystemBackground);
|
||||
|
||||
auto& header = view().add_subview<UI::View>(LG::Rect(0, 0, 0, 0));
|
||||
header.set_background_color(LG::Color(222, 232, 227));
|
||||
|
||||
auto& label = header.add_subview<UI::Label>(LG::Rect(0, 0, 16, 22));
|
||||
label.set_text_color(LG::Color(14, 72, 19));
|
||||
label.set_text("Monitor");
|
||||
label.set_font(LG::Font::system_bold_font(LG::Font::SystemTitleSize));
|
||||
label.set_width(label.preferred_width());
|
||||
|
||||
auto& switch_tab = view().add_subview<UI::StackView>(LG::Rect(0, 0, 102, 18));
|
||||
switch_tab.set_spacing(8);
|
||||
switch_tab.layer().set_corner_mask(LG::CornerMask(4));
|
||||
switch_tab.layer().set_shading(LG::Shading(LG::Shading::Box));
|
||||
switch_tab.set_spacing(4);
|
||||
|
||||
auto& cpu_tab = switch_tab.add_arranged_subview<UI::Button>();
|
||||
cpu_tab.set_content_edge_insets(UI::EdgeInsets(4, 10, 4, 10));
|
||||
cpu_tab.set_background_color(LG::Color(248, 250, 231));
|
||||
cpu_tab.set_title("CPU");
|
||||
cpu_tab.set_title_color(LG::Color::DarkSystemText);
|
||||
|
||||
auto& mem_tab = switch_tab.add_arranged_subview<UI::Button>();
|
||||
mem_tab.set_content_edge_insets(UI::EdgeInsets(4, 10, 4, 10));
|
||||
mem_tab.set_background_color(LG::Color::White);
|
||||
mem_tab.set_title("Memory");
|
||||
mem_tab.set_title_color(LG::Color::DarkSystemText);
|
||||
|
||||
auto& cpu_label = view().add_subview<UI::Label>(LG::Rect(0, 0, 180, 16));
|
||||
auto& cpu_graphs_stackview = view().add_subview<UI::StackView>(LG::Rect(0, 0, 184, 100));
|
||||
cpu_graphs_stackview.set_distribution(UI::StackView::Distribution::FillEqually);
|
||||
cpu_graphs_stackview.set_spacing(10);
|
||||
|
||||
view().add_constraint(UI::Constraint(header, UI::Constraint::Attribute::Left, UI::Constraint::Relation::Equal, 0));
|
||||
view().add_constraint(UI::Constraint(header, UI::Constraint::Attribute::Top, UI::Constraint::Relation::Equal, 0));
|
||||
view().add_constraint(UI::Constraint(header, UI::Constraint::Attribute::Right, UI::Constraint::Relation::Equal, 0));
|
||||
view().add_constraint(UI::Constraint(header, UI::Constraint::Attribute::Height, UI::Constraint::Relation::Equal, 60));
|
||||
|
||||
view().add_constraint(UI::Constraint(label, UI::Constraint::Attribute::Left, UI::Constraint::Relation::Equal, UI::SafeArea::Left));
|
||||
view().add_constraint(UI::Constraint(label, UI::Constraint::Attribute::CenterY, UI::Constraint::Relation::Equal, header, UI::Constraint::Attribute::CenterY, 1, 0));
|
||||
|
||||
view().add_constraint(UI::Constraint(switch_tab, UI::Constraint::Attribute::Left, UI::Constraint::Relation::Equal, UI::SafeArea::Left));
|
||||
view().add_constraint(UI::Constraint(switch_tab, UI::Constraint::Attribute::CenterY, UI::Constraint::Relation::Equal, header, UI::Constraint::Attribute::Bottom, 1, 0));
|
||||
|
||||
view().add_constraint(UI::Constraint(cpu_label, UI::Constraint::Attribute::Left, UI::Constraint::Relation::Equal, UI::SafeArea::Left));
|
||||
view().add_constraint(UI::Constraint(cpu_label, UI::Constraint::Attribute::Bottom, UI::Constraint::Relation::Equal, UI::SafeArea::Bottom));
|
||||
|
||||
view().add_constraint(UI::Constraint(cpu_graphs_stackview, UI::Constraint::Attribute::Left, UI::Constraint::Relation::Equal, UI::SafeArea::Left));
|
||||
view().add_constraint(UI::Constraint(cpu_graphs_stackview, UI::Constraint::Attribute::Right, UI::Constraint::Relation::Equal, UI::SafeArea::Right));
|
||||
view().add_constraint(UI::Constraint(cpu_graphs_stackview, UI::Constraint::Attribute::Top, UI::Constraint::Relation::Equal, switch_tab, UI::Constraint::Attribute::Bottom, 1, 8));
|
||||
view().add_constraint(UI::Constraint(cpu_graphs_stackview, UI::Constraint::Attribute::Bottom, UI::Constraint::Relation::Equal, cpu_label, UI::Constraint::Attribute::Top, 1, -8));
|
||||
|
||||
for (int i = 0; i < cpu_count(); i++) {
|
||||
auto& graph = cpu_graphs_stackview.add_arranged_subview<GraphView>(200);
|
||||
cpu_graphs_stackview.add_constraint(UI::Constraint(graph, UI::Constraint::Attribute::Height, UI::Constraint::Relation::Equal, cpu_graphs_stackview, UI::Constraint::Attribute::Height, 1, 0));
|
||||
cpu_graphs.push_back(&graph);
|
||||
}
|
||||
|
||||
view().set_needs_layout();
|
||||
|
||||
UI::App::the().event_loop().add(LFoundation::Timer([&] {
|
||||
update_data();
|
||||
cpu_label.set_text(std::string("Load ") + std::to_string(state.cpu_load[0]) + "%");
|
||||
cpu_label.set_needs_display();
|
||||
},
|
||||
1000, LFoundation::Timer::Repeat));
|
||||
}
|
||||
|
||||
int update_cpu_load()
|
||||
{
|
||||
int fd_proc_stat = open("/proc/stat", O_RDONLY);
|
||||
int offset = 0;
|
||||
read(fd_proc_stat, buf, sizeof(buf));
|
||||
|
||||
for (int i = 0; i < cpu_count(); i++) {
|
||||
int user_time, system_time, idle_time;
|
||||
int num;
|
||||
offset += sscanf(buf + offset, "cpu%d %d 0 %d %d\n", &num, &user_time, &system_time, &idle_time);
|
||||
int diff_user_time = user_time - state.cpu_old_user_time[i];
|
||||
int diff_system_time = system_time - state.cpu_old_system_time[i];
|
||||
int diff_idle_time = idle_time - state.cpu_old_idle_time[i];
|
||||
state.cpu_old_user_time[i] = user_time;
|
||||
state.cpu_old_system_time[i] = system_time;
|
||||
state.cpu_old_idle_time[i] = idle_time;
|
||||
|
||||
if (diff_user_time + diff_system_time + diff_idle_time == 0) {
|
||||
state.cpu_load[i] = 0;
|
||||
} else {
|
||||
state.cpu_load[i] = (diff_user_time + diff_system_time) * 100 / (diff_user_time + diff_system_time + diff_idle_time);
|
||||
}
|
||||
|
||||
cpu_graphs[i]->add_new_value(state.cpu_load[i]);
|
||||
}
|
||||
|
||||
close(fd_proc_stat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void update_data()
|
||||
{
|
||||
update_cpu_load();
|
||||
}
|
||||
|
||||
private:
|
||||
int m_cpu_count;
|
||||
int fd_proc_stat;
|
||||
std::vector<GraphView*> cpu_graphs;
|
||||
|
||||
struct State {
|
||||
std::vector<int> cpu_load;
|
||||
std::vector<int> cpu_old_user_time;
|
||||
std::vector<int> cpu_old_system_time;
|
||||
std::vector<int> cpu_old_idle_time;
|
||||
};
|
||||
State state;
|
||||
};
|
||||
Reference in New Issue
Block a user