genode/repos/demo/src/app/launchpad/loadbar.h

274 lines
5.8 KiB
C++

/*
* \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 <typename PT>
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<PT, _LW, _LH> _cover { };
Scout::Fade_icon<PT, _LW, _LH> _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 <typename PT>
class Kbyte_loadbar : public Loadbar<PT>
{
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<PT>::value()), " / ",
Kbytes(Loadbar<PT>::max_value()));
Loadbar<PT>::txt(_label.string());
}
public:
Kbyte_loadbar(Loadbar_listener *listener, Scout::Font *font = 0):
Loadbar<PT>(listener, font)
{
_update_label();
}
void value(int val)
{
Loadbar<PT>::value(val);
_update_label();
}
void max_value(int max_value)
{
Loadbar<PT>::max_value(max_value);
_update_label();
}
};
#endif