ede/ede-notify-daemon/NotifyWindow.cpp
Sanel Zukan 04b5c9d1f0 Better resize support.
Body widget is by default hidden and summary is lowered a little bit,
to fill space gap. Also this commit fixes 'position' calls for output
widgets, as this function for these widgets will move cursor at given
position, instead to move widget. Yuck!
2012-05-15 10:28:08 +00:00

164 lines
4.0 KiB
C++

#include <FL/Fl.H>
#include <FL/x.H>
#include <FL/fl_draw.H>
#include <edelib/Debug.h>
#include <edelib/IconLoader.h>
#include <edelib/Nls.h>
#include <edelib/Netwm.h>
#include "NotifyWindow.h"
/* default sizes for window */
#define DEFAULT_W 280
#define DEFAULT_H 75
#define DEFAULT_EXPIRE 2000
EDELIB_NS_USING(IconLoader)
EDELIB_NS_USING(netwm_window_set_type)
EDELIB_NS_USING(ICON_SIZE_MEDIUM)
EDELIB_NS_USING(NETWM_WINDOW_TYPE_NOTIFICATION)
extern int FL_NORMAL_SIZE;
static void close_cb(Fl_Widget*, void *w) {
NotifyWindow *win = (NotifyWindow*)w;
win->hide();
}
static void timeout_cb(void *w) {
close_cb(0, w);
}
NotifyWindow::NotifyWindow() : Fl_Window(DEFAULT_W, DEFAULT_H) {
FL_NORMAL_SIZE = 12;
type(NOTIFYWINDOW_TYPE);
color(FL_BACKGROUND2_COLOR);
box(FL_BORDER_BOX);
begin();
closeb = new Fl_Button(255, 10, 20, 20, "x");
closeb->box(FL_FLAT_BOX);
closeb->down_box(FL_DOWN_BOX);
closeb->color(FL_BACKGROUND2_COLOR);
closeb->labelsize(12);
closeb->tooltip(_("Close this notification"));
closeb->clear_visible_focus();
closeb->callback(close_cb, this);
imgbox = new Fl_Box(10, 10, 48, 48);
imgbox->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
summary = new Fl_Multiline_Output(65, 10, 185, 25);
/* use flat box so text can be drawn correctly */
summary->box(FL_FLAT_BOX);
summary->cursor_color(FL_BACKGROUND2_COLOR);
body = new Fl_Multiline_Output(65, 35, 185, 25);
/* use flat box so text can be drawn correctly */
body->box(FL_FLAT_BOX);
body->cursor_color(FL_BACKGROUND2_COLOR);
end();
/*
* by default body text is hidden and summary is lowered a little bit
* NOTE: I'm using 'resize' as 'position' for Fl_Input/Fl_Output means something different
*/
summary->resize(summary->x(), summary->y() + (summary->h() / 2), summary->w(), summary->h());
body->hide();
border(0);
}
void NotifyWindow::set_icon(const char *img) {
E_RETURN_IF_FAIL(IconLoader::inited());
E_RETURN_IF_FAIL(img != NULL);
IconLoader::set(imgbox, img, ICON_SIZE_MEDIUM);
}
void NotifyWindow::set_body(const char *s) {
summary->resize(summary->x(), summary->y() - (summary->h() / 2), summary->w(), summary->h());
body->value(s);
body->show();
}
void NotifyWindow::show(void) {
if(exp != 0) {
if(exp == -1) exp = DEFAULT_EXPIRE;
Fl::add_timeout((double)exp / (double)1000, timeout_cb, this);
}
Fl_Window::show();
netwm_window_set_type(fl_xid(this), NETWM_WINDOW_TYPE_NOTIFICATION);
}
#define INPUT_VALID(i) ((i)->visible() && (i)->size() > 0)
void NotifyWindow::resize(int X, int Y, int W, int H) {
/*
* do not call further if window is shown: different strategy is needed as every time
* window is re-configured, this will be called
*/
if(shown()) return;
/* resize summary if needed */
if(summary->size() > 0) {
int fw = 0, fh = 0;
fl_font(summary->textfont(), summary->textsize());
fl_measure(summary->value(), fw, fh);
if(fw > summary->w()) {
int d = fw - summary->w();
summary->resize(summary->x(), summary->y(), fw, summary->h());
/* move X button */
closeb->position(closeb->x() + d, closeb->y());
/* resize body too */
if(INPUT_VALID(body)) body->resize(body->x(), body->y(), body->w() + d, body->h());
W += d;
/* this depends on window position */
X -= d;
}
if(fh > summary->h()) {
int d = fh - summary->h();
summary->resize(summary->x(), summary->y(), summary->w(), fh);
/* move body down */
if(INPUT_VALID(body)) body->resize(body->x(), body->y() + d, body->w(), body->h());
H += d;
Y -= d;
}
}
/* resize body if needed */
if(INPUT_VALID(body)) {
int fw = 0, fh = 0;
fl_font(body->textfont(), body->textsize());
fl_measure(body->value(), fw, fh);
if(fw > body->w()) {
int d = fw - body->w();
body->resize(body->x(), body->y(), fw, body->h());
/* move X button again */
closeb->position(closeb->x() + d, closeb->y());
W += d;
X -= d;
}
if(fh > body->h()) {
int d = fh - body->h();
body->resize(body->x(), body->y(), body->w(), fh);
H += d;
Y -= d;
}
}
Fl_Window::resize(X, Y, W, H);
}