/* * \brief Loadbar widget * \author Norman Feske * \date 2006-08-30 */ /* * Copyright (C) 2006-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ #ifndef _LOADBAR_H_ #define _LOADBAR_H_ #include "widgets.h" #include "styles.h" #include "fade_icon.h" #define LOADBAR_RGBA _binary_loadbar_rgba_start #define REDBAR_RGBA _binary_redbar_rgba_start #define WHITEBAR_RGBA _binary_whitebar_rgba_start extern unsigned char LOADBAR_RGBA[]; extern unsigned char REDBAR_RGBA[]; extern unsigned char WHITEBAR_RGBA[]; struct Loadbar_listener { virtual ~Loadbar_listener() { } virtual void loadbar_changed(int mx) = 0; }; class Loadbar_event_handler : public Scout::Event_handler { private: /* * Noncopyable */ Loadbar_event_handler(Loadbar_event_handler const &); Loadbar_event_handler &operator = (Loadbar_event_handler const &); Loadbar_listener *_listener; public: Loadbar_event_handler(Loadbar_listener *listener): _listener(listener) { } /** * Event handler interface */ void handle_event(Scout::Event const &ev) override { static int key_cnt; using Scout::Event; if (ev.type == Event::PRESS) key_cnt++; if (ev.type == Event::RELEASE) key_cnt--; if (ev.type == Event::PRESS || ev.type == Event::MOTION) if (_listener && key_cnt > 0) _listener->loadbar_changed(ev.mouse_position.x()); } }; template class Loadbar : public Scout::Parent_element { private: /* * Noncopyable */ Loadbar(Loadbar const &); Loadbar &operator = (Loadbar const &); enum { _LW = 16, _LH = 16, }; bool _active; Scout::Fade_icon _cover { }; Scout::Fade_icon _bar { }; Loadbar_event_handler _ev_handler; int _value; int _max_value; const char *_txt; int _txt_w, _txt_h, _txt_len; Scout::Font *_font; void _update_bar_geometry(int w) { using namespace Scout; int max_w = w - _LW; int bar_w = (_value * max_w) / _max_value; bar_w += _LW; _bar.geometry(Rect(Point(_bar.position().x(), _bar.position().y()), Area(bar_w, _LH))); } public: Loadbar(Loadbar_listener *listener = 0, Scout::Font *font = 0): _active(listener ? true : false), _ev_handler(listener), _value(0), _max_value(100), _txt(""), _txt_w(0), _txt_h(0), _txt_len(0), _font(font) { using namespace Scout; _min_size = Area(_min_size.w(), _LH); _cover.rgba(LOADBAR_RGBA); _cover.alpha(100); _cover.focus_alpha(150); _bar.rgba(_active ? REDBAR_RGBA : LOADBAR_RGBA); _bar.alpha(_active ? 150 : 255); _bar.default_alpha(150); if (_active) event_handler(&_ev_handler); append(&_cover); append(&_bar); } int value_by_xpos(int xpos) { xpos -= _LW/2; int max_w = _size.w() - _LW; return Scout::max(Scout::min((_max_value * xpos) / max_w, _max_value), 0); } int value() { return _value; } void value(int value) { _value = Scout::max(Scout::min(value, _max_value), 0); _update_bar_geometry(_size.w()); } int max_value() { return _max_value; } void max_value(int max_value) { _max_value = max_value; _update_bar_geometry(_size.w()); } void txt(const char *txt) { if (!_font) return; _txt = txt; _txt_w = _font->string_width(_txt, Scout::strlen(_txt)).decimal(); _txt_h = _font->bounding_box().h(); _txt_len = Scout::strlen(_txt); } /** * Element interface */ void format_fixed_width(int w) override { using namespace Scout; _cover.geometry(Rect(Point(0, 0), Area(w, _LH))); _update_bar_geometry(w); _min_size = Scout::Area(w, _min_size.h()); } void draw(Scout::Canvas_base &canvas, Scout::Point abs_position) override { Parent_element::draw(canvas, abs_position); if (!_font) return; using namespace Scout; int txt_x = abs_position.x() + _position.x() + max((_size.w() - _txt_w)/2, 8UL); int txt_y = abs_position.y() + _position.y() + max((_size.h() - _txt_h)/2, 0UL) - 1; /* shrink clipping area to text area (limit too long label) */ int cx1 = canvas.clip().x1(), cy1 = canvas.clip().y1(); int cx2 = canvas.clip().x2(), cy2 = canvas.clip().y2(); int nx1 = max(cx1, _position.x() + abs_position.x()); int ny1 = max(cy1, _position.y() + abs_position.y()); int nx2 = min(cx2, nx1 + (int)_size.w() - 8); int ny2 = min(cy2, ny1 + (int)_size.h()); canvas.clip(Rect(Point(nx1, ny1), Area(nx2 - nx1 + 1, ny2 - ny1 + 1))); canvas.draw_string(txt_x , txt_y+1, _font, Color(0,0,0,150), _txt, strlen(_txt)); canvas.draw_string(txt_x , txt_y, _font, Color(255,255,255,230), _txt, strlen(_txt)); /* reset clipping */ canvas.clip(Rect(Point(cx1, cy1), Area(cx2 - cx1 + 1, cy2 - cy1 + 1))); } void mfocus(int flag) override { if (!_active) return; _bar.mfocus(flag); _cover.mfocus(flag); } }; template class Kbyte_loadbar : public Loadbar { private: typedef Genode::String<32> Label; Label _label { }; struct Kbytes { int const _value; Kbytes(int value) : _value(value) { } void print(Genode::Output &out) const { if (_value >= 10*1024) Genode::print(out, _value/1024, " MByte"); else Genode::print(out, _value, " KByte"); } }; void _update_label() { _label = Label(Kbytes(Loadbar::value()), " / ", Kbytes(Loadbar::max_value())); Loadbar::txt(_label.string()); } public: Kbyte_loadbar(Loadbar_listener *listener, Scout::Font *font = 0): Loadbar(listener, font) { _update_label(); } void value(int val) { Loadbar::value(val); _update_label(); } void max_value(int max_value) { Loadbar::max_value(max_value); _update_label(); } }; #endif