ede/eiconman/DesktopIcon.cpp

318 lines
6.8 KiB
C++
Raw Normal View History

2007-05-22 18:53:17 +04:00
/*
* $Id$
*
* Eiconman, desktop and icon manager
* Part of Equinox Desktop Environment (EDE).
* Copyright (c) 2000-2007 EDE Authors.
*
* This program is licensed under terms of the
* GNU General Public License version 2 or newer.
* See COPYING for details.
*/
#include "DesktopIcon.h"
#include "eiconman.h"
#include "Utils.h"
#include <FL/Fl.h>
#include <FL/fl_draw.h>
#include <FL/Fl_Shared_Image.h>
#include <FL/x.h>
2007-05-22 18:53:17 +04:00
#include <edelib/Debug.h>
#include <edelib/IconTheme.h>
#define USE_SHAPE 1
#ifdef USE_SHAPE
#include <X11/extensions/shape.h>
#endif
2007-05-22 18:53:17 +04:00
// minimal icon size
2007-05-22 18:53:17 +04:00
#define ICONSIZE 48
// spaces around box in case of large/small icons
#define OFFSET_W 16
#define OFFSET_H 16
// label offset from icon y()+h(), so selection box can be drawn nicely
#define LABEL_OFFSET 2
DesktopIcon::DesktopIcon(GlobalIconSettings* gs, IconSettings* is, int bg) :
Fl_Widget(is->x, is->y, ICONSIZE, ICONSIZE) {
2007-05-22 18:53:17 +04:00
EASSERT(gs != NULL);
2007-05-22 18:53:17 +04:00
lwidth = lheight = 0;
focus = false;
micon = NULL;
2007-05-22 18:53:17 +04:00
/*
* GlobalIconSettings is shared from desktop so we only
* reference it. On other hand IconSettings is not shared
* and we must construct a copy from given parameter
*/
globals = gs;
2007-05-22 18:53:17 +04:00
settings = new IconSettings;
settings->name = is->name;
settings->cmd = is->cmd;
settings->icon = is->icon;
settings->type = is->type;
settings->key_name= is->key_name;
2007-05-22 18:53:17 +04:00
// x,y are not needed since x(), y() are filled with it
label(settings->name.c_str());
if(!settings->icon.empty()) {
const char* nn = settings->icon.c_str();
//edelib::String ipath = edelib::IconTheme::get(nn, edelib::ICON_SIZE_MEDIUM);
edelib::String ipath = edelib::IconTheme::get(nn, edelib::ICON_SIZE_HUGE);
2007-06-23 15:31:36 +04:00
if(!ipath.empty()) {
Fl_Image* img = Fl_Shared_Image::get(ipath.c_str());
if(img) {
int img_w = img->w();
int img_h = img->h();
2007-06-23 15:31:36 +04:00
// resize box if icon is larger
if(img_w > ICONSIZE || img_h > ICONSIZE)
size(img_w + OFFSET_W, img_h + OFFSET_H);
2007-06-23 15:31:36 +04:00
image(img);
} else
EDEBUG(ESTRLOC ": Unable to load %s\n", ipath.c_str());
2007-06-23 15:31:36 +04:00
} else
EDEBUG(ESTRLOC ": Got empty icon name ?!?\n");
}
/*
2007-05-22 18:53:17 +04:00
EDEBUG(ESTRLOC ": Got label: %s\n", label());
EDEBUG(ESTRLOC ": Got image: %s\n", settings->icon.c_str());
EDEBUG(ESTRLOC ": Got x/y : %i %i\n", x(), y());
*/
//Use desktop color as color for icon background
color(bg);
2007-05-22 18:53:17 +04:00
align(FL_ALIGN_WRAP);
2007-05-22 18:53:17 +04:00
update_label_size();
}
DesktopIcon::~DesktopIcon() {
EDEBUG("DesktopIcon::~DesktopIcon()\n");
2007-05-22 18:53:17 +04:00
if(settings)
delete settings;
2007-05-22 18:53:17 +04:00
if(micon)
delete micon;
}
void DesktopIcon::update_label_size(void) {
lwidth = globals->label_maxwidth;
lheight= 0;
/*
* make sure current font size/type is set (internaly to fltk)
* so fl_measure() can correctly calculate label width and height
*/
fl_font(labelfont(), labelsize());
2007-05-22 18:53:17 +04:00
fl_measure(label(), lwidth, lheight, align());
2007-05-22 18:53:17 +04:00
lwidth += 8;
lheight += 4;
}
void DesktopIcon::drag(int x, int y, bool apply) {
if(!micon) {
micon = new MovableIcon(this);
#if USE_SHAPE
/*
* This is used to calculate correct window startup/ending
* position since icon is placed in the middle of the box.
*
* Opposite, window (shaped) will have small but noticeable 'jump off' and
* dropped icon position will not be at the exact place where was dropped.
*/
int ix, iy;
ix = iy = 0;
if(image()) {
ix = (w()/2) - (image()->w()/2);
iy = (h()/2) - (image()->h()/2);
}
2007-05-22 18:53:17 +04:00
micon->position(micon->x() + ix, micon->y() + iy);
#endif
micon->show();
} else {
EASSERT(micon != NULL);
2007-05-22 18:53:17 +04:00
micon->position(x, y);
}
2007-05-22 18:53:17 +04:00
if(apply) {
#if USE_SHAPE
int ix, iy;
ix = iy = 0;
if(image()) {
ix = (w()/2) - (image()->w()/2);
iy = (h()/2) - (image()->h()/2);
}
position(micon->x() - ix, micon->y() - iy);
#else
2007-05-22 18:53:17 +04:00
position(micon->x(), micon->y());
#endif
2007-05-22 18:53:17 +04:00
delete micon;
micon = NULL;
2007-05-22 18:53:17 +04:00
}
}
// Used only in Desktop::move_selection
int DesktopIcon::drag_icon_x(void) {
if(!micon)
return x();
else
2007-05-22 18:53:17 +04:00
return micon->x();
}
// Used only in Desktop::move_selection
int DesktopIcon::drag_icon_y(void) {
if(!micon)
return y();
else
return micon->y();
}
void DesktopIcon::fast_redraw(void) {
EASSERT(parent() != NULL && "Impossible !");
// LABEL_OFFSET + 2 include selection box line height too
parent()->damage(FL_DAMAGE_ALL, x(), y(), w(), h() + lheight + LABEL_OFFSET + 2);
}
void DesktopIcon::draw(void) {
//draw_box(FL_UP_BOX, FL_BLACK);
if(image() && (damage() & FL_DAMAGE_ALL)) {
Fl_Image* im = image();
// center image in the box
int ix = (w()/2) - (im->w()/2);
int iy = (h()/2) - (im->h()/2);
ix += x();
iy += y();
im->draw(ix, iy);
2007-05-22 18:53:17 +04:00
}
if(globals->label_draw && (damage() & (FL_DAMAGE_ALL | EDAMAGE_CHILD_LABEL))) {
int X = x() + w()-(w()/2)-(lwidth/2);
int Y = y() + h() + LABEL_OFFSET;
Fl_Color old = fl_color();
2007-05-22 18:53:17 +04:00
if(!globals->label_transparent) {
fl_color(globals->label_background);
fl_rectf(X, Y, lwidth, lheight);
2007-05-22 18:53:17 +04:00
}
fl_color(globals->label_foreground);
fl_draw(label(), X, Y, lwidth, lheight, align(), 0, 0);
2007-05-22 18:53:17 +04:00
if(is_focused()) {
/*
* draw focused box on our way so later
* this can be used to draw customised boxes
*/
fl_line_style(FL_DOT);
2007-05-22 18:53:17 +04:00
fl_color(globals->label_foreground);
2007-05-22 18:53:17 +04:00
fl_push_matrix();
fl_begin_loop();
fl_vertex(X,Y);
fl_vertex(X+lwidth,Y);
fl_vertex(X+lwidth,Y+lheight);
fl_vertex(X,Y+lheight);
fl_vertex(X,Y);
fl_end_loop();
fl_pop_matrix();
2007-05-22 18:53:17 +04:00
// revert to default line style
fl_line_style(0);
2007-05-22 18:53:17 +04:00
}
2007-05-23 16:43:50 +04:00
// revert to old color whatever that be
fl_color(old);
2007-05-22 18:53:17 +04:00
}
}
int DesktopIcon::handle(int event) {
switch(event) {
case FL_FOCUS:
case FL_UNFOCUS:
case FL_ENTER:
case FL_LEAVE:
return 1;
/*
* We have to handle FL_MOVE too, if want to get only once
* FL_ENTER when entered or FL_LEAVE when leaved.
*/
case FL_MOVE:
return 1;
case FL_PUSH:
return 1;
case FL_RELEASE:
if(Fl::event_clicks() > 0)
EDEBUG(ESTRLOC ": EXECUTE: %s\n", settings->cmd.c_str());
return 1;
default:
break;
}
return 1;
2007-05-22 18:53:17 +04:00
}
MovableIcon::MovableIcon(DesktopIcon* ic) : Fl_Window(ic->x(), ic->y(), ic->w(), ic->h()), icon(ic), mask(0) {
2007-05-22 18:53:17 +04:00
EASSERT(icon != NULL);
set_override();
color(ic->color());
2007-05-22 18:53:17 +04:00
begin();
/*
* Force box be same width/height as icon so it
* can fit inside masked window.
*/
#ifdef USE_SHAPE
Fl_Image* img = ic->icon_image();
if(img)
icon_box = new Fl_Box(0, 0, img->w(), img->h());
else
icon_box = new Fl_Box(0, 0, w(), h());
#else
icon_box = new Fl_Box(0, 0, w(), h());
#endif
icon_box->image(ic->icon_image());
end();
2007-05-22 18:53:17 +04:00
}
MovableIcon::~MovableIcon() {
if(mask)
XFreePixmap(fl_display, mask);
}
void MovableIcon::show(void) {
if(!shown())
Fl_X::make_xid(this);
#ifdef USE_SHAPE
if(icon->icon_image()) {
mask = create_mask(icon->icon_image());
if(mask)
XShapeCombineMask(fl_display, fl_xid(this), ShapeBounding, 0, 0, mask, ShapeSet);
}
#endif
2007-05-22 18:53:17 +04:00
}